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.

usb_dev_cserial.inf drivers do not install under Windows 10

Other Parts Discussed in Thread: EK-TM4C1294XL, TMS320F28069

I am trying to install the drivers for a composite device on Windows 10.  I will need to support this in the field.

I had similar issues installing the ICDI drivers but was able to get around the issue by turning of driver signature enforcement.  That procedure didn't work in this case.

The composite device installs, but shows a warning flag under device manager.   The device events shows that the serial devices contained in the composite did not properly install:

I have spent an entire day on this with no luck.


The EKTM41294xl device is running the example code usb_dev_cserial project with no changes.   The .inf files are "out of the box"  from the TI windows driver folder. 

  • Hello Dan

    Windows 10 is becoming a night mare for us as well. We are checking with other groups as they may also run into the same or may be having the same issues as us.

    Regards
    Amit
  • Both USB serial sub-devices have the same type of error message that the driver could not be migrated.

  • Thanks for escalating this.

    I pulled out an old machine with Win7/Pro. I am installing the drivers there.

    More information:

    The Composite device driver USBccgg is a generic from Microsoft. It looks like it installed under Win10.

    The next step in the install seems to be to enumerate the devices within the composite and install their drivers. Under Win7, these come up as OtherDevices with the yellow exclamation. The procedure for updating these drivers is well described in the Stellaris driver install manual.

    However, they do not seem to be listed in the Device Manager under Win10, so there is no way I have found to update them.

    If I get the Win7 machine running, I can continue development, but I will need a Win10 solution before I go to market.

    Thanks for your help.

    Dan
  • Hello Dan

    That is what it seems for USB Serial as well. Microsoft drivers seem to get preference over anything else.

    Regards
    Amit
  • Is there any update on this?
    I have boards being built assuming the issue will be resolved.
  • Hello Dan,

    Rest assured the issue shall be resolved at the earliest. I do understand boards are being built and we have other customers that are also awaiting the update (so we are in the direct line of fire to get the USB on Win 10 resolved).

    The holiday season makes it difficult to pull in the correct set of people. With next 2 weeks we have a clear window to work with developers to understand the issue and if required make a tactical patch on the forum before releasing it on www.ti.com

    Regards
    Amit
  • Dan and Amit,

    I have been seeing the same issue. I get same USB Composite Device cannot start error code 10 on both a Dell XPS 15 (running Windows 8.1 64-bit) and a Dell Inspiron 15R (running Windows 10 64-bit). I see the same "could not be migrated" error.

    The interesting thing is that on my Dell XPS 15 (Windows 8.1), I get this problem when connecting to any of the USB ports (4 total).

    On the Dell 15R (Windows 10), I get it only on 2 of the 4 possible USB ports. It seems to work fine on the other two. I have tried to determine what the difference between these ports are, but have come up with no good answer.

    I was able to first get it working on a Dell XPS 9500 Desktop (running Windows 7 64-bit), with all USB ports working there.

    It still may be a Windows 8.1/Windows 10 issue, but it also seems related to particular USB ports as well?

    If there are any suggestions to track down the difference between the Dell Inspiron 15R USB ports and why 2 work and 2 report the issue, let me know. I really need to get this working on my development machine, the Dell XPS 15 (Windows 8.1) where non of the USB ports work with the composite device.

    As a side note, if I change the software to only initialize a single CDC (not a composite device), that works just fine. It only seems to be the TM4C129x and USB Composite Device that causes this issue.

    Don ...
  • Hello Don,

    Interesting. Can you check if the ports are USB2.0 or USB3.0 on the two machines?

    Regards
    Amit
  • Amit,

    On the Dell Inspiron 15R (Windows 10 64-bit), it has two (2) USB 3.0 ports, where the dev kit USB Composite Device fails to start (code 10), but the other two (2) USB ports are 2.0 and seem to work.

    On the Dell XPS 15 9530 (Windows 8.1 64-bit), it has three (3) USB 3.0 ports, where the dev kit USB Composite Device fails to start (code 10), and one (1) USB 2.0 (power share) port and the dev kit USB Composite Device fails to start (code 10).

    On my Dell 9500 desktop (Windows 7 64-bit), all USB ports are 2.0 and seem to work. I have used a tool to view the USB information on this machine, USB Device Tree Viewer V2.5.8 (www.uwe-sieber.de/usbtreeview_e.html) and it shows up as a USB Composite Device - COM62, COM63 (both virtual com ports present). One thing I do notice, although working on this machine, the Device Descriptor seems to have an error for the iManufacturer, iProduct, and iSerialNumber? Below is the information captured by this tool. Maybe, this causes some USB controllers /or the Microsoft Composite USB driver to error?

    On the ports that do not work, e.g. my Dell XPS 15 9530, the USB Composite Device cannot start (Code 10), thus does not show up with the USB Device Tree Viewer (i.e. not connected due to failure).

    Don...

    Report from the USB Device Tree Viewer V2.5.8 tool, Dell XPS 9500 USB 2.0 port (Windows 7 64-bit):
    =========================== USB Port2 ===========================

    Connection Status : 0x01 (Device is connected)
    Port Chain : 5-2

    ======================== USB Device ========================

    +++++++++++++++++ Device Information ++++++++++++++++++
    Device Description : USB Composite Device
    Device Path : \\?\usb#vid_1cbe&pid_0007#12345678#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    Device ID : USB\VID_1CBE&PID_0007\12345678
    Driver KeyName : {36fc9e60-c465-11cf-8056-444553540000}\0102 (GUID_DEVCLASS_USB)
    Driver : C:\Windows\system32\DRIVERS\usbccgp.sys (Version: 6.1.7601.18328 Date: 2013-11-26)
    Driver Inf : C:\Windows\inf\usb.inf
    Legacy BusType : PNPBus
    Class : USB
    Service : usbccgp
    Enumerator : USB
    Location Info : Port_#0002.Hub_#0002
    Location IDs : PCIROOT(0)#PCI(1A01)#USBROOT(0)#USB(2)
    Container ID : {573422b9-55b1-5658-9065-13731848c675}
    Manufacturer Info : (Standard USB Host Controller)
    Capabilities : 0x94 (Removable, UniqueID, SurpriseRemovalOK)
    Address : 2
    Problem Code : 0
    Power State : D0 (supported: D0, D2, D3, wake from D0, wake from D2)
    Child Device 1 : TivaWare USB Serial Port
    Device ID : USB\VID_1CBE&PID_0007&MI_00\6&B9401D1&0&0000
    Class : Ports
    COM-Port : COM62 (\Device\USBSER001)
    Child Device 2 : TivaWare USB Serial Command Port
    Device ID : USB\VID_1CBE&PID_0007&MI_02\6&B9401D1&0&0002
    Class : Ports
    COM-Port : COM63 (\Device\USBSER002)

    ---------------- Connection Information ---------------
    Connection Index : 0x02 (2)
    Connection Status : 0x01 (DeviceConnected)
    Current Config Value : 0x01
    Device Address : 0x01 (1)
    Is Hub : 0x00 (no)
    Number Of Open Pipes : 0x06 (6)
    Device Bus Speed : 0x01 (Full-Speed)
    Pipe0ScheduleOffset : 0x00 (0)
    Pipe1ScheduleOffset : 0x00 (0)
    Pipe2ScheduleOffset : 0x00 (0)
    Pipe3ScheduleOffset : 0x00 (0)
    Pipe4ScheduleOffset : 0x00 (0)
    Pipe5ScheduleOffset : 0x00 (0)

    ------------------ Device Descriptor ------------------
    bLength : 0x12 (18 bytes)
    bDescriptorType : 0x01 (Device Descriptor)
    bcdUSB : 0x110 (USB Version 1.10)
    bDeviceClass : 0xEF (Miscellaneous)
    bDeviceSubClass : 0x02
    bDeviceProtocol : 0x01 (IAD)
    bMaxPacketSize0 : 0x40 (64 bytes)
    idVendor : 0x1CBE
    idProduct : 0x0007
    bcdDevice : 0x100
    iManufacturer : 0x01 (String Descriptor 1)
    *!*ERROR String descriptor 1 not found
    iProduct : 0x02 (String Descriptor 2)
    *!*ERROR String descriptor 2 not found
    iSerialNumber : 0x03 (String Descriptor 3)
    *!*ERROR String descriptor 3 not found
    bNumConfigurations : 0x01

    ------------------ String Descriptors -----------------
    ------ String Descriptor 0 ------
    bLength : 0x04 (4 bytes)
    bDescriptorType : 0x03 (String Descriptor)
    Language ID[0] : 0x0409 (English - United States)

    ---------------- Configuration Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x02 (Configuration Descriptor)
    wTotalLength : 0x008D (141 bytes)
    bNumInterfaces : 0x04
    bConfigurationValue : 0x01
    iConfiguration : 0x00 (No String Descriptor)
    bmAttributes : 0x80
    D7: Reserved, set 1 : 0x01
    D6: Self Powered : 0x00 (no)
    D5: Remote Wakeup : 0x00 (no)
    D4..0: Reserved, set 0 : 0x00
    MaxPower : 0x7D (250 mA)

    ------------------- IAD Descriptor --------------------
    bLength : 0x08 (8 bytes)
    bDescriptorType : 0x0B
    bFirstInterface : 0x00
    bInterfaceCount : 0x02
    bFunctionClass : 0x02 (Communications and CDC Control)
    bFunctionSubClass : 0x02
    bFunctionProtocol : 0x01
    iFunction : 0x00 (No String Descriptor)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x00
    bAlternateSetting : 0x00
    bNumEndpoints : 0x01 (1 Endpoint)
    bInterfaceClass : 0x02 (Communications and CDC Control)
    bInterfaceSubClass : 0x02
    bInterfaceProtocol : 0x01
    iInterface : 0x00 (No String Descriptor)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x00 (Header Functional Descriptor)
    bcdCDC : 0x110 (CDC Version 1.10)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x04 (4 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x02 (Abstract Control Management Functional Descriptor)
    bmCapabilities : 0x06

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x06 (Union Functional Descriptor)
    bControlInterface : 0x00
    bSubordinateInterface[0] : 0x01

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x01 (Call Management Functional Descriptor)
    bmCapabilities : 0x01
    bDataInterface : 0x01

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
    bmAttributes : 0x03 (TransferType=Interrupt)
    wMaxPacketSize : 0x0010 (16 bytes) (16 bytes)
    bInterval : 0x01 (1 ms)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x01
    bAlternateSetting : 0x00
    bNumEndpoints : 0x02 (2 Endpoints)
    bInterfaceClass : 0x0A (CDC-Data)
    bInterfaceSubClass : 0x00
    bInterfaceProtocol : 0x00
    iInterface : 0x00 (No String Descriptor)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x82 (Direction=IN EndpointID=2)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x01 (Direction=OUT EndpointID=1)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ------------------- IAD Descriptor --------------------
    bLength : 0x08 (8 bytes)
    bDescriptorType : 0x0B
    bFirstInterface : 0x02
    bInterfaceCount : 0x02
    bFunctionClass : 0x02 (Communications and CDC Control)
    bFunctionSubClass : 0x02
    bFunctionProtocol : 0x01
    iFunction : 0x00 (No String Descriptor)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x02
    bAlternateSetting : 0x00
    bNumEndpoints : 0x01 (1 Endpoint)
    bInterfaceClass : 0x02 (Communications and CDC Control)
    bInterfaceSubClass : 0x02
    bInterfaceProtocol : 0x01
    iInterface : 0x00 (No String Descriptor)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x00 (Header Functional Descriptor)
    bcdCDC : 0x110 (CDC Version 1.10)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x04 (4 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x02 (Abstract Control Management Functional Descriptor)
    bmCapabilities : 0x06

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x06 (Union Functional Descriptor)
    bControlInterface : 0x02
    bSubordinateInterface[0] : 0x03

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x01 (Call Management Functional Descriptor)
    bmCapabilities : 0x01
    bDataInterface : 0x03

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
    bmAttributes : 0x03 (TransferType=Interrupt)
    wMaxPacketSize : 0x0010 (16 bytes) (16 bytes)
    bInterval : 0x01 (1 ms)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x03
    bAlternateSetting : 0x00
    bNumEndpoints : 0x02 (2 Endpoints)
    bInterfaceClass : 0x0A (CDC-Data)
    bInterfaceSubClass : 0x00
    bInterfaceProtocol : 0x00
    iInterface : 0x00 (No String Descriptor)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x83 (Direction=IN EndpointID=3)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x02 (Direction=OUT EndpointID=2)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)
  • Hello Don,

    As an experiment can we change the file usbdcdc.c and change the g_pui8CDCSerDeviceDescriptor field for the string identifier to 0

    1, // Manufacturer string identifier.
    2, // Product string identifier.
    3, // Product serial number.

    change as
    0, // Manufacturer string identifier.
    0, // Product string identifier.
    0, // Product serial number.

    recompile the usblib and link the new usblib driverlib to the project.

    Regards
    Amit
  • Amit,

    I made the requested change to usbdcdc.c and change the g_pui8CDCSerDeviceDescriptor field as shown.

    Still get a cannot start (Code 10) on the XPS 15 9530 (Windows 8.1 64-bit) USB 2.0 port.

    On the XPS 9500 (Windows 7 64-bit) USB 2.0 port, it still seems to work. This is the output from the USB Device Tree Viewer:

    =========================== USB Port2 ===========================

    Connection Status : 0x01 (Device is connected)
    Port Chain : 6-2

    ======================== USB Device ========================

    +++++++++++++++++ Device Information ++++++++++++++++++
    Device Description : USB Composite Device
    Device Path : \\?\usb#vid_1cbe&pid_0007#12345678#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    Device ID : USB\VID_1CBE&PID_0007\12345678
    Driver KeyName : {36fc9e60-c465-11cf-8056-444553540000}\0102 (GUID_DEVCLASS_USB)
    Driver : C:\Windows\system32\DRIVERS\usbccgp.sys (Version: 6.1.7601.18328 Date: 2013-11-26)
    Driver Inf : C:\Windows\inf\usb.inf
    Legacy BusType : PNPBus
    Class : USB
    Service : usbccgp
    Enumerator : USB
    Location Info : Port_#0002.Hub_#0003
    Location IDs : PCIROOT(0)#PCI(1A02)#USBROOT(0)#USB(2)
    Container ID : {573422b9-55b1-5658-9065-13731848c675}
    Manufacturer Info : (Standard USB Host Controller)
    Capabilities : 0x94 (Removable, UniqueID, SurpriseRemovalOK)
    Address : 2
    Problem Code : 0
    Power State : D0 (supported: D0, D2, D3, wake from D0, wake from D2)
    Child Device 1 : TivaWare USB Serial Port
    Device ID : USB\VID_1CBE&PID_0007&MI_00\6&B9401D1&0&0000
    Class : Ports
    COM-Port : COM62 (\Device\USBSER001)
    Child Device 2 : TivaWare USB Serial Command Port
    Device ID : USB\VID_1CBE&PID_0007&MI_02\6&B9401D1&0&0002
    Class : Ports
    COM-Port : COM63 (\Device\USBSER002)

    ---------------- Connection Information ---------------
    Connection Index : 0x02 (2)
    Connection Status : 0x01 (DeviceConnected)
    Current Config Value : 0x01
    Device Address : 0x02 (2)
    Is Hub : 0x00 (no)
    Number Of Open Pipes : 0x06 (6)
    Device Bus Speed : 0x01 (Full-Speed)
    Pipe0ScheduleOffset : 0x00 (0)
    Pipe1ScheduleOffset : 0x00 (0)
    Pipe2ScheduleOffset : 0x00 (0)
    Pipe3ScheduleOffset : 0x00 (0)
    Pipe4ScheduleOffset : 0x00 (0)
    Pipe5ScheduleOffset : 0x00 (0)

    ------------------ Device Descriptor ------------------
    bLength : 0x12 (18 bytes)
    bDescriptorType : 0x01 (Device Descriptor)
    bcdUSB : 0x110 (USB Version 1.10)
    bDeviceClass : 0xEF (Miscellaneous)
    bDeviceSubClass : 0x02
    bDeviceProtocol : 0x01 (IAD)
    bMaxPacketSize0 : 0x40 (64 bytes)
    idVendor : 0x1CBE
    idProduct : 0x0007
    bcdDevice : 0x100
    iManufacturer : 0x01 (String Descriptor 1)
    *!*ERROR String descriptor 1 not found
    iProduct : 0x02 (String Descriptor 2)
    *!*ERROR String descriptor 2 not found
    iSerialNumber : 0x03 (String Descriptor 3)
    *!*ERROR String descriptor 3 not found
    bNumConfigurations : 0x01

    ------------------ String Descriptors -----------------
    ------ String Descriptor 0 ------
    bLength : 0x04 (4 bytes)
    bDescriptorType : 0x03 (String Descriptor)
    Language ID[0] : 0x0409 (English - United States)

    ---------------- Configuration Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x02 (Configuration Descriptor)
    wTotalLength : 0x008D (141 bytes)
    bNumInterfaces : 0x04
    bConfigurationValue : 0x01
    iConfiguration : 0x00 (No String Descriptor)
    bmAttributes : 0x80
    D7: Reserved, set 1 : 0x01
    D6: Self Powered : 0x00 (no)
    D5: Remote Wakeup : 0x00 (no)
    D4..0: Reserved, set 0 : 0x00
    MaxPower : 0x7D (250 mA)

    ------------------- IAD Descriptor --------------------
    bLength : 0x08 (8 bytes)
    bDescriptorType : 0x0B
    bFirstInterface : 0x00
    bInterfaceCount : 0x02
    bFunctionClass : 0x02 (Communications and CDC Control)
    bFunctionSubClass : 0x02
    bFunctionProtocol : 0x01
    iFunction : 0x00 (No String Descriptor)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x00
    bAlternateSetting : 0x00
    bNumEndpoints : 0x01 (1 Endpoint)
    bInterfaceClass : 0x02 (Communications and CDC Control)
    bInterfaceSubClass : 0x02
    bInterfaceProtocol : 0x01
    iInterface : 0x00 (No String Descriptor)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x00 (Header Functional Descriptor)
    bcdCDC : 0x110 (CDC Version 1.10)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x04 (4 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x02 (Abstract Control Management Functional Descriptor)
    bmCapabilities : 0x06

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x06 (Union Functional Descriptor)
    bControlInterface : 0x00
    bSubordinateInterface[0] : 0x01

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x01 (Call Management Functional Descriptor)
    bmCapabilities : 0x01
    bDataInterface : 0x01

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
    bmAttributes : 0x03 (TransferType=Interrupt)
    wMaxPacketSize : 0x0010 (16 bytes) (16 bytes)
    bInterval : 0x01 (1 ms)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x01
    bAlternateSetting : 0x00
    bNumEndpoints : 0x02 (2 Endpoints)
    bInterfaceClass : 0x0A (CDC-Data)
    bInterfaceSubClass : 0x00
    bInterfaceProtocol : 0x00
    iInterface : 0x00 (No String Descriptor)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x82 (Direction=IN EndpointID=2)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x01 (Direction=OUT EndpointID=1)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ------------------- IAD Descriptor --------------------
    bLength : 0x08 (8 bytes)
    bDescriptorType : 0x0B
    bFirstInterface : 0x02
    bInterfaceCount : 0x02
    bFunctionClass : 0x02 (Communications and CDC Control)
    bFunctionSubClass : 0x02
    bFunctionProtocol : 0x01
    iFunction : 0x00 (No String Descriptor)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x02
    bAlternateSetting : 0x00
    bNumEndpoints : 0x01 (1 Endpoint)
    bInterfaceClass : 0x02 (Communications and CDC Control)
    bInterfaceSubClass : 0x02
    bInterfaceProtocol : 0x01
    iInterface : 0x00 (No String Descriptor)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x00 (Header Functional Descriptor)
    bcdCDC : 0x110 (CDC Version 1.10)

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x04 (4 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x02 (Abstract Control Management Functional Descriptor)
    bmCapabilities : 0x06

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x06 (Union Functional Descriptor)
    bControlInterface : 0x02
    bSubordinateInterface[0] : 0x03

    -------------- CDC Interface Descriptor ---------------
    bFunctionLength : 0x05 (5 bytes)
    bDescriptorType : 0x24 (Interface)
    bDescriptorSubType : 0x01 (Call Management Functional Descriptor)
    bmCapabilities : 0x01
    bDataInterface : 0x03

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
    bmAttributes : 0x03 (TransferType=Interrupt)
    wMaxPacketSize : 0x0010 (16 bytes) (16 bytes)
    bInterval : 0x01 (1 ms)

    ---------------- Interface Descriptor -----------------
    bLength : 0x09 (9 bytes)
    bDescriptorType : 0x04 (Interface Descriptor)
    bInterfaceNumber : 0x03
    bAlternateSetting : 0x00
    bNumEndpoints : 0x02 (2 Endpoints)
    bInterfaceClass : 0x0A (CDC-Data)
    bInterfaceSubClass : 0x00
    bInterfaceProtocol : 0x00
    iInterface : 0x00 (No String Descriptor)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x83 (Direction=IN EndpointID=3)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    ----------------- Endpoint Descriptor -----------------
    bLength : 0x07 (7 bytes)
    bDescriptorType : 0x05 (Endpoint Descriptor)
    bEndpointAddress : 0x02 (Direction=OUT EndpointID=2)
    bmAttributes : 0x02 (TransferType=Bulk)
    wMaxPacketSize : 0x0040 (64 bytes) (64 bytes)
    bInterval : 0x00 (ignored)

    Don ...
  • Hello Don,

    Thanks for the added support on the issue debug. I will have some time this week to see if the MS architecture for USB enumeration has changed and to run some experiments on a VM Win10 machine which is reporting a similar failure.

    Regards
    Amit
  • Any progress on Composit USB/Serial drivers for Window 10?  My boards are in and I am ready to check this out.

    I tried connecting the device to a USB 2 hub on the motherboard. (Has two USB3, one USB2 hubs).  No difference.. 

  • Hello Dan,

    The Win10 issue has been resolved. We are trying to see how to release a temporary patch within TivaWare.

    Regards
    Amit
  • When will the patch be available? I am having the same issue.
    Thanks.
  • Hello Audrey,

    Hopefully soon. I can understand the anguish caused by the delay, but we are trying to ensure that a good-to-go release of the drivers is done.

    Regards
    Amit

  • Hello Dan, Andrey,

    Attached is a patch that may be evaluated till the official TivaWare release contains the same. Please note that this is an evaluation-only patch, so any issues with the same must be reported back to the thread, so that we can help you out faster.

    windows_drivers.zip

    Regards

    Amit

  • Hello Amit,

    I'm still getting an issue with the patch.

    The driver looks like it updated correctly and lists in the Win Device Manager as TivaWare USB serial but our software is unable to connect to the COM port. For debugging purposes I tried connecting to the USB COM port with Realterm and I get the message "The parameter is incorrect." 

    The driver version is 21.3.129 with a date of 1/20/2016. Is this the correct driver? Anything I can do to help debug/resolve the issue?

    Thank you,

    Juan

  • Hello Juan

    The driver version and date is correct (as it has been pulled from the next TivaWare release).

    Can you send a screenshot of the Device Manger and try using TeraTerm?

    Also make sure that no other COM port application is open and try a unplug-plug as well before starting TeraTerm.

    Regards
    Amit
  • Hi Amit,

    Strangely with Tera Term I can use the driver no problem. I was able to connect and communicate with our program by manually entering data through Tera Term.

    However our software uses the Microsoft function SetCommState and SetCommTimeouts and each is reporting issues. Using the same version of the software on both the PC-side and TivaWare-side we can communicate with the radio board on a Win8 machine but not Win10. Any recommendations?

    Thanks,
    Juan

    Device Manager Screenshot

  • Hello Juan,

    No, idea why that would be an issue on Win10. Maybe would be able to help.

    Regards
    Amit
  • I purchased a new computer with Windows 10 simply to assure that the prior attempts to install drivers hadn't screwed up something.

    I made a restore point so I can unwind bad installs.

    I did install the TI Stellaris library 2.1.2.111 which installed the IDCI drivers.  That worked just fine.

    I took the TM4C129 EK and installed the CSerial demo.  I then tested it using the prior Windows 7 drivers on an old Windows 7 machine.  Worked fine.  So I know I have a good image in the launchpad.

    I then tried to install on the new Win10 pc:

    • Plugged Launchpad into a USB 2 port on the computer (It also has USB3.1). 
    • The IDCI port works fine
    • The composite serial port comes up with an error - device not recognized.
    • I then opened the Composite Device and attempted to update the drivers with 2.1.2.111 (1/31/16 attempt).

    I gave up to wait for a TI Solution.

    I downloaded the new pre-release Windows drivers posted last week. 

    Today, I tried again to update the driver.  

    • Right click on  failed USB Composite Device
    • Properties/Details/Hardware IDs
    • Verify that the VID/PID are correct for this Launchpad (they are)
    • Driver/Update Driver
    • Navigate to the new folder C:\ti\Windows Drivers (where I unzipped the new package)

    Update says that the latest drivers are already installed. 

    Is there some other process I need to be doing?  

    It is Composite Driver that doesn't seem to be starting.

    Dan

  • Hello Dan

    MS has been changing their driver implementation. Can you check the following (I think it to be similar post)

    e2e.ti.com/.../480438

    Regards
    Amit
  • Dan Beadle said:
    I then opened the Composite Device and attempted to update the drivers with 2.1.2.111

    The driver packages (under windows_drivers folder) in TivaWare_C_Series-2.1.2.111 have trouble of driver signing.

    Dan Beadle said:
    Update says that the latest drivers are already installed. 

    If you would install one of these packages once, you have to clean up the former installation, before installing fixed package.

    Here is the procedure.

    1) Clean up Device instance(s) on registry
    You may use Device Manager with devmgr_show_nonpresent_devices option, but USBDeview utility is handy for composite device, because it sorts out device instances in the order of VID/PID
    - WebPage: www.nirsoft.net/.../usb_devices_view.html
    - USBDeview x86: www.nirsoft.net/.../usbdeview.zip
    - USBDeview x64: www.nirsoft.net/.../usbdeview-x64.zip

    Run USBDeview on your PC
    - USB device instances are listed up
    Scroll the list to left, to see "Vendor ID" column: click on "Vendor ID" title
    - the list is sorted by VID/PID
    Scroll down to see "Vendor ID": 0x1CBE, "Product ID": 0x0007
    - You'll find a couple of lines, which have this VID/PID
    Using shift click, select all lines of this VID/PID
    Right click on the selected lines, choose "uninstall" from the right menu

    Now that the device instances on the registry have been cleaned

    2) Clean up DriverStrore and oemxx.inf in Windows\inf folder
    Open command prompt window under administrator privilege, copy these two lines (right click - paste) to the dialog.

    cd %WINDIR%\inf
    findstr "Vid_1CBE&Pid_0007" *.inf

    Above "findstr" lists up oemXX.inf (XX: number) files, which include TI's Cserial VID/PID.
    Delete these "oemXX.inf" files using pnputil command (which deletes DriverStore and .pnf files, too)

    pnputil -d oemXX.inf


    Tsuneo

  • Thank you.  Very helpful and detailed.  

    I loaded the USB Dev View tool.  I found just one line with PID_1CBE&Vid_0007.  I deleted it.  Then I ran the findstr in the \inf folder.  None found:

    C:\Windows\INF>findstr "Vid_1CBE&Pid_0007" *.inf

    C:\Windows\INF>findstr "Vid_1CBE" *.inf
    oem38.inf:%DESCRIPTION_1%=BulkInstall,USB\Vid_1CBE&Pid_00FD&MI_02
    oem38.inf:%DESCRIPTION_1%=BulkInstall,USB\Vid_1CBE&Pid_00FD&MI_02
    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FD&MI_00
    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_00
    oem53.inf:%DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_02
    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FD&MI_00
    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_00
    oem53.inf:%DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_02

    C:\Windows\INF>

    The VIDs found are for the IDCI and a single instance of the usb serial running on our board.  

    I then plugged in the board.  

    The device still does not register (NOTE:  this is still using the original demo code on the 129EK board)  

    I get the same composite driver fails to migrate.  

    I tried Update Driver, but when I point to the newest TI drivers, I still get the message that the best driver is already installed.

    Thank you for your help. 

    I am also reviewing your post Amit recommended 
    e2e.ti.com/.../480438    

    Is that a better approach?  Seems like more learning curve, but perhaps worth it as I will want to add a third comm port.

  • I also noticed a couple of items.  

    The other instance of the USBSerial is the TM4C123gl board. It also used the same PID/VID and serial number ("12345678").  

    I used USB Viewer to uninstall it, then searched the INF folder.  No Pid_1CBE&Vid_0007 found.  

    Next, I reconnected the board.  

    Although the install failed the same way, I notice that an entry was made for the PID/VID with the serial number.  

    Here is info from USBDevViewer  

  • findstr is "case sensitive".
    Try this search literal for 1CBE/0007

    cd %WINDIR%\inf
    findstr "[Vv][Ii][Dd]_1[Cc][Bb][Ee]&[Pp][Ii][Dd]_0007" oem*.inf

    Tsuneo
  • Thanks.. I had already tried Pid_1cbe, assuming they would all be the same case..

    Trying the regex, I got nothing, so I removed 0007 and got the expected oem files:

    C:\Windows\INF>cd %WINDIR%\inf

    C:\Windows\INF>findstr "Vid_1CBE&Pid_0007" *.inf

    C:\Windows\INF>findstr "[Vv][Ii][Dd]_1[Cc][Bb][Ee]&[Pp][Ii][Dd]_0007" oem*.inf

    C:\Windows\INF>findstr "[Vv][Ii][Dd]_1[Cc][Bb][Ee]&[Pp][Ii][Dd]" oem*.inf

    oem0.inf:%USB\StellarisDFUDevice.DeviceDesc% =USB_Install, USB\VID_1CBE&PID_00FF

    oem0.inf:%USB\StellarisDFUDevice.DeviceDesc% =USB_Install, USB\VID_1CBE&PID_00FF

    oem38.inf:%DESCRIPTION_1%=BulkInstall,USB\Vid_1CBE&Pid_00FD&MI_02

    oem38.inf:%DESCRIPTION_2%=USB_Install,USB\VID_1CBE&PID_00FD&MI_03

    oem38.inf:%DESCRIPTION_2%=USB_Install,USB\VID_1CBE&PID_00FE&MI_04

    oem38.inf:%DESCRIPTION_1%=BulkInstall,USB\Vid_1CBE&Pid_00FD&MI_02

    oem38.inf:%DESCRIPTION_2%=USB_Install,USB\VID_1CBE&PID_00FD&MI_03

    oem38.inf:%DESCRIPTION_2%=USB_Install,USB\VID_1CBE&PID_00FE&MI_04

    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FD&MI_00

    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_00

    oem53.inf:%DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_02

    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FD&MI_00

    oem53.inf:%DESCRIPTION_0%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_00

    oem53.inf:%DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_00FE&MI_02

    Does that make any sense?  The composite device events remember that it saw the 0007 Pid/Vid in January.  So,  it is stored somewhere.  

  • After a lot of mis-steps, I found a very simple solution to installing the CSerial drivers - DON"T... 

    From another post by Tsuneo Chinzei, I found that the Stellaris USB CDC driver defaults to USB 1.1. He showed code to change that to 2.0

    In USB_dev_cserial.c:

    USBDCompositeInit(0, &g_sCompDevice, DESCRIPTOR_DATA_SIZE,
    g_pucDescriptorData);

    Add this:

    // Winsusb
    // Force bcdUSB field of the Device Descriptor into 0x0200 (USB 2.0) -- T.C.
    // because of the requirement of MS OS string descriptor
    g_sCompDevice.sPrivateData.sDeviceDescriptor.bcdUSB = 0x0200;

    Once I did that, Windows 10 simply recognizes USB Serial devices as native - no driver needed. 

    I verified that without this change, Win 10 does not recognize the device, but with it, no install files are needed for composite USB Serial.

    The link above discusses a composite Bulk/DFU.  I learned a lot about Microsoft's WinUSB no-inf driver.  Turned out that I didn't need it... yet.  I do plan to add DFU support which will probably require using MS OS Descriptors.... It took a while to understand how that system works, but the payoff is big - no drivers required.  The best approach to understand his code is compare the _DFU source files to the corresponding sample files to see what changes he made - they were really minimal.  Most involved the DFU control code - not USB enumeration items.  Thanks Tsuneo..

    I also extended the sample to support three serial ports, which is what I needed all along.  After correcting a few typos, the CSerial demo was supporting three USB Serial comm ports... 

    Back to work on the key features of the product...

  • Hello Dan,

    Glad that you are up and running. A link to the MS pages would be a great resource for others looking to do the same.

    Regards
    Amit
  • To get around the inf package not loading for USB_CSerial demo, I did the following:

    • Requested a unique PID for my product.  This made sure that the pre-loaded drivers were not interfering.  Changed the source to use my PID
    • Changed the USB version from 1.1 to 2.00 (see earlier post).
    • Compiled and tested.  
    • It just installed!  
    • I tried removing the USB Version 2.00 and it again failed, worked when I restored that patch.

    I found a lot of helpful information from Microsoft.  

    MS OS Descriptors

    WinUSB.dll  (CDC is NOT in this list as far as I can tell).  WinUSB can still be used, but takes more work that my final solution.

    USBSer (This link provided the information to really simplify the code)

    "If you want to load Usbser.sys automatically, set the class code to 02 and subclass code to 02 in the Device Descriptor. For more information, see USB communications device class (or USB CDC) Specification found on the USB DWG website. With this approach, you are not required to distribute INF files for your device because the system uses Usbser.inf."  Simple.. 

  • Hi Dan,

    I tried the change you described above, and I was able to get it working on a couple of USB ports (Windows 10 Dell Laptop). Several of the other USB ports would still show an error for the composite device "This cannot start. (Code 10)".

    Can you confirm for your Windows 10 system, were the USB ports that are working USB 2.0 or USB 3.0? It seems the ports that are NOT working on my Windows 10 Dell Laptop are the USB 3.0 ports.

    Amit, any further ideas that could explain the difference I am seeing between USB ports?

    Don ...

  • Hello Don,

    We have tested it on a USB3.0 VM port and the new drivers were working. Did you try w/o the changes?

    Regards
    Amit
  • I am having an issue with USB 3 hubs too.  I am not sure if that is a TI issue

    My HW has two TM4C123F parts going into an USB2507 hub chip. I put a USB memory Thumb Drive on the hub.  When I hook the hub to a USB3.0 hub, no joy.  Plug it into a USB 2.0 hub plugged into the same USB3.0 hub, it all works.   So I think this may be a problem with noise on the USB signal.  Not TI.  

  • I also tried with Win7. With my changes, I still need an INF as Win7 doesn't have in-box drivers. I have three ports so I took the TI INF and made these changes:
    - added one more description. -MI_o4 for the third interface
    - Comment out .cat file line. No signature on Win32 systems.

    This came up,and reported three USB-Serial ports
  • Hello Amit,

    I haven't heard from Tsuneo Chinzei regarding the Microsoft functions not working with this version of the driver patch release. Is there another function that's recommended? So far I've only been able to get this to work in Tera Term.

    Thanks,

    Juan

  • Hello Juan

    Details please, which MS functions are you referring to?

    Regards
    Amit
  • Hello Amit,

    Sorry, this is in follow up to my prior question on Feb 11 and your reply shortly after.

    Our software uses the Microsoft function SetCommState and SetCommTimeouts and each is reporting issues. Using the same version of the software on both side (PC and ARM) we can communicate with the radio board on a Win8 machine but not Win10. Any recommendations?


    Thanks,
    Juan
  • Hello Juan,

    Thanks for refreshing my memory. Unfortunately, I am not an expert on MS function, so really cannot help you out here.

    Regards
    Amit
  • Hello Tsuneo,

    I've been trying to get the patch windows driver to work but can't seem to get the board to work with anything other than Tera Term. Even Putty and Realterm present issues when I try to connect to the COM port.

    Our software uses the Microsoft function SetCommState and SetCommTimeouts and each is also reporting issues when trying to connect. Using the same version of the software on both the PC-side and TivaWare-side we can communicate with the radio board on a Win8 machine but not Win10.

    Amit mentioned earlier in this thread you may be able to help. Any recommendations?

    Thanks,
    Juan
  • Hey Dan,

    Is your device is being working fine with windows 10 now?

  • Yes, I have this working, but my environment is limited to just a few machines, so I am using un-signed drivers.

    It turns out that I would not have been able to use the TI drivers as-is.  My device is three USB Serial Ports - not two like the sample driver.  And, I added DFU to be able to update the firmware without opening the box.

    It turns out to be fairly simple to install un-signed drivers in Win/10 as long as the user has ADMIN rights.  My customer is deploying this device to its engineers and on their production line  (It is a piece of test equipment) so they are able to do the few extra steps it takes to install un-signed INFs.

    First, I requested two PIDs from TI. That process was amazingly simple.  Mine are 0232 and 0233.   Then I hacked the various samples until I got something to work.  

    Here is the INF I am using for one of the Tiva C processors in my test equipment:

    ;

    ;   TivaWare USB CDC (serial) driver installation file.

    ;

    ;   Copyright (c) 2010 Texas Instruments Incorporated.  All rights reserved.

    ;

    [Version]

    Signature="$Windows NT$"

    ;Class = IoSimDeviceClass

    Class=Ports

    ; CDC UsbSer class..

    ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}

    Provider=%MFGNAME%

    ;CatalogFile.NTamd64=IOSim_amd64.cat

    ;CatalogFile.NTx86=IOSim_x86.cat

    DriverVer=04/19/2016,16.29.00.01

    [SourceDisksNames]

    1=%DISKNAME%,,,

    [SourceDisksFiles]

    %12%\usbser.sys=1

    [Manufacturer]

    %MFGNAME%=VirComDevice,NT,NTamd64

    [DestinationDirs]

    DefaultDestDir = 12

    [VirComDevice.NT]

    %DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_00

    %DESCRIPTION_2%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_02

    %DESCRIPTION_3%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_04

    [VirComDevice.NTamd64]

    %DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_00   ; Com1

    %DESCRIPTION_2%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_02   ; Com2

    %DESCRIPTION_3%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_04   ; Com3

    [ClassInstall32]

    AddReg=AddReg_ClassInstall

    [AddReg_ClassInstall]

    HKR,,,,"%IoSimGroupName%"

    HKR,,Icon,,-1

    [DriverInstall.NT]

    Include=mdmcpq.inf

    CopyFiles=FakeModemCopyFileSection

    AddReg=DriverInstall.NT.AddReg

    [DriverInstall.NT.AddReg]

    HKR,,DevLoader,,*ntkern

    HKR,,NTMPDriver,,usbser.sys

    HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"

    HKR,,DeviceInterfaceGUIDs,0x10000,"{D17C772B-AF45-4041-9979-AAFE96BF6398}"

    [DriverInstall.NT.Services]

    AddService=usbser, 0x00000002, DriverServiceInst

    [DriverServiceInst]

    DisplayName=%SERVICE%

    ServiceType=1

    StartType=3

    ErrorControl=1

    ServiceBinary=%12%\usbser.sys

    [FakeModemCopyFileSection]

    ;;; DFU Section.........................................

    [DFU_Install.NTx86]

    Include=winusb.inf

    Needs=WINUSB.NT

    CopyFiles=System32_CopyFiles

    [DFU_Install.NTamd64]

    Include=winusb.inf

    Needs=WINUSB.NT

    CopyFiles=SysWOW64_CopyFiles

    CopyFiles=System64_CopyFiles

    [DFU_Install.NTx86.Services]

    Include=winusb.inf

    AddService=WinUSB,0x00000002,WinUSB_ServiceInstall

    [DFU_Install.NTamd64.Services]

    Include=winusb.inf

    AddService=WinUSB,0x00000002,WinUSB_ServiceInstall

    [WinUSB_ServiceInstall]

    DisplayName     = %WinUSB_SvcDesc%

    ServiceType     = 1

    StartType       = 3

    ErrorControl    = 1

    ServiceBinary   = %12%\WinUSB.sys

    [DFU_Install.NTx86.Wdf]

    KmdfService=WINUSB, WinDFU_Install

    [DFU_Install.NTamd64.Wdf]

    KmdfService=WINUSB, WinDFU_Install

    [WinDFU_Install]

    KmdfLibraryVersion=1.9

    [DFU_Install.NTx86.HW]

    AddReg=Dev_AddReg

    [DFU_Install.NTamd64.HW]

    AddReg=Dev_AddReg

    [Dev_AddReg]

    HKR,,DeviceInterfaceGUIDs,0x10000,"{D17C772B-AF45-4041-9979-AAFE96BF6398}"

    [DFU_Install.NTx86.CoInstallers]

    AddReg=CoInstallers_AddReg

    CopyFiles=CoInstallers_CopyFiles

    [DFU_Install.NTamd64.CoInstallers]

    AddReg=CoInstallers_AddReg

    CopyFiles=CoInstallers_CopyFiles

    [CoInstallers_AddReg]

    HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller","WinUSBCoInstaller2.dll"

    [CoInstallers_CopyFiles]

    WinUSBCoInstaller2.dll

    WdfCoInstaller01009.dll

    [System32_CopyFiles]

    lmusbdll.dll

    lmusbdll.lib

    lmdfu.dll

    lmdfu.lib

    [System64_CopyFiles]

    lmusbdll.dll, lmusbdll64.dll

    lmusbdll.lib, lmusbdll64.lib

    lmdfu.dll, lmdfu64.dll

    lmdfu.lib, lmdfu64.lib

    [SysWOW64_CopyFiles]

    lmusbdll.dll

    lmusbdll.lib

    lmdfu.dll

    lmdfu.lib

    [DestinationDirs]

    DefaultDestDir = 12

    CoInstallers_CopyFiles=11

    System32_CopyFiles=10,system32

    SysWOW64_CopyFiles=10,syswow64

    System64_CopyFiles=10,system32

    ICDISystem32_CopyFiles=10,system32

    ICDISysWOW64_CopyFiles=10,syswow64

    ICDISystem64_CopyFiles=10,system32

    ; ================= Source Media Section =====================

    [SourceDisksNames]

    1=%DISKNAME%,,,

    2=%DISKNAME%,,,\i386

    3=%DISKNAME%,,,\amd64

    [SourceDisksFiles]

    %12%\usbser.sys=1

    [SourceDisksFiles.x86]

    WinUSBCoInstaller2.dll=2

    WdfCoInstaller01009.dll=2

    lmusbdll.dll=2

    lmusbdll.lib=2

    lmusbicdi.dll=2

    lmusbicdi.lib=2

    lmdfu.dll=2

    lmdfu.lib=2

    [SourceDisksFiles.amd64]

    WinUSBCoInstaller2.dll=3

    WdfCoInstaller01009.dll=3

    lmusbdll.dll=2

    lmusbdll.lib=2

    lmusbicdi.dll=2

    lmusbicdi.lib=2

    lmdfu.dll=2

    lmdfu.lib=2

    lmusbdll64.dll=3

    lmusbdll64.lib=3

    lmusbicdi64.dll=3

    lmusbicdi64.lib=3

    lmdfu64.dll=3

    lmdfu64.lib=3

    ; =================== Strings ===================

    [Strings]

    MFGNAME       = "Incline Softworks, LLC"

    DISKNAME      = "TivaWare Composite Serial Device"

    DESCRIPTION_1 = "IOSIM Com1"

    DESCRIPTION_2 = "IOSIM Com2"

    DESCRIPTION_3 = "IOSIM Com3"

    DESCRIPTION_4 = "IOSIM FW Update"

    SERVICE       = "IOSim Control"

    IoSimGroupName= "IOSimulators"

     

    The various DLLs are in the TI Drivers folder, under the INFs they provide.

     

    Some notes I could have used are below.  I had expected the Serial Port feature  to be kind of a drop-in.  And, it can be if you are just doing 1 or 2 ports and copy a TI demo exactly for the USB features.  Deviate on a feature and their INFs may not work for you.  I added features.  In hindsight, another solution would have taken less research.  The flip side, I learned more than I wanted to know. And I am far, far from being an expert.  Most of the INF is standard boilerplate you need and is well documented by MS and others (See Jan Axleton's books)

    • ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}  - This is the Windows device class for a serial device.  In Win8 on, this can let the system install and run serial ports without user drivers.  It gives the PNP code a hint of what features it needs.
    • [VirComDevice.NT]

    %DESCRIPTION_1%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_00
    %DESCRIPTION_2%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_02
    %DESCRIPTION_3%=DriverInstall,USB\Vid_1CBE&Pid_0233&MI_04 -- These lines define the three serial port instances. Serial Ports require two end-points, so the instance (PID_mypid&MI_0x) is bumped by 2.

    • [DriverInstall.NT.AddReg]

    HKR,,DevLoader,,*ntkern
    HKR,,NTMPDriver,,usbser.sys
    HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
    HKR,,DeviceInterfaceGUIDs,0x10000,"{D17C772B-AF45-4041-9979-AAFE96BF6398}" - This is the stuff that helps Win7 configure. 
    USBSer.sys is the actual Windows driver that we use.  This is how we get away without building a custom driver.  
    MsPorts and SerialPortPropPageProvider handle enumeration.  If you have a unique serial number for your device, the same ports are reassigned no matter which USB port you connect it to.  Without that, two devices connected will keep generating new com port numbers.  Can get messy quickly.

    • [Strings]

    MFGNAME = "Incline Softworks, LLC"
    DISKNAME = "TivaWare Composite Serial Device"
    DESCRIPTION_1 = "IOSIM Com1"
    DESCRIPTION_2 = "IOSIM Com2"
    DESCRIPTION_3 = "IOSIM Com3"
    DESCRIPTION_4 = "IOSIM FW Update"
    SERVICE = "IOSim Control"
    IoSimGroupName= "IOSimulators"  -- I customized the strings a bit.  Added my company name, but still give TI credit.  The Descriptions were important for me.  The device exposes 6 serial ports and two DFU devices. (It has a built in hub to connect the two Tivas to one external USB cable).  Win10 does a nice job of displaying these port names. It lets the customer sort out what the various ports do.  Note that the Windows COM port number is different:  my IOSIM Com3 might be on Windows Com7 or Com44

    Again, I am no expert.  But if you have questions, feel free to ask.


    Dan

  • Hello TI

    Any update regarding this issue with Windows 10?  I am also facing the similar issue with TMS320F28069UPFPS USB CDC and DFU class drivers (composite device). We are using these drivers for Windows 7 from more than a year. But while connecting same device with Windows 10 PC, the PC is not recognizing it as a specific device instead acting as Windows native device (as mentioned earlier). Even though I am installing the specific drivers manually, but it is not communicating with our device as expected. I have also attached the code trace log for failure message. 

    Here I am attaching the code-trace log: Error message - Can't read language table.

    This issue is quite critical for us as we are moving for production. Also I do not have much experience with USB and Windows drivers. So please let me know if any further information is required.

    Thanks in advance

  • I am having a very similar issue. I am using a EK-TM4C1294XL. I am using windows 10, and when I plug in the debug side of the board, everything is working well. I can put in code from code composer or LM Flash Programmer. My problem lies in installing the USB Composite Device. This is supposed to be (from my understanding) additional Stellaris Virtual Serial Ports. In device status, I have the message "This device cannot start. Code 10". I have also tried this with a Windows 8.1 machine and it still does not work.

    I have tried disabling the signatures.
    I have tried reinstalling the drivers.
    I have tried updating the drivers to no success.

    Are there any other options that I have overlooked?
  • The answer on this board has helped move me in the right direction. I can at the very least start communicating with the board appropriately now, although the drivers are still not installing properly.

    e2e.ti.com/.../480438

    Look for the answer Tsuneo Chinzei has given.
  • Hello Stephen,

    For one, have you tried the new patch for TivaWare we released this week? You can get it at: http://software-dl.ti.com/tiva-c/SW-TM4C/latest/index_FDS.html  - it is listed as "SW-TM4C-2.1.4.178.PATCH-1.0.zip"

    There are new Windows drivers here which work on Win10 and should be used - though this alone won't solve the composite device issue.

    Now then, specifically regarding the Composite device issue, there is a file which needs to be changed in the usblib for TivaWare.

    I am attaching the new .c file below, which should be used to replace the file in the [Install Path]\TivaWare_C_Series-2.1.4.178\usblib\device folder. From there the usb_dev_cserial example should be re-compiled and re-flashed.

    //****************************************************************************
    //
    // usbdcomp.c - USB composite device class driver.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.4.178 of the Tiva USB Library.
    //
    //****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/usb.h"
    #include "usblib/usblib.h"
    #include "usblib/usblibpriv.h"
    #include "usblib/usb-ids.h"
    #include "usblib/usbcdc.h"
    #include "usblib/device/usbdevice.h"
    #include "usblib/device/usbdcdc.h"
    #include "usblib/device/usbdcomp.h"
    
    //****************************************************************************
    //
    //! \addtogroup composite_device_class_api
    //! @{
    //
    //****************************************************************************
    
    //****************************************************************************
    //
    // Device Descriptor.  This is stored in RAM to allow several fields to be
    // changed at runtime based on the client's requirements.
    //
    //****************************************************************************
    static uint8_t g_pui8CompDeviceDescriptor[] =
    {
        18,                     // Size of this structure.
        USB_DTYPE_DEVICE,       // Type of this structure.
        USBShort(0x110),        // USB version 1.1 (if we say 2.0, hosts assume
                                // high-speed - see USB 2.0 spec 9.2.6.6)
        USB_CLASS_MISC,         // USB Device Class (spec 5.1.1)
        USB_MISC_SUBCLASS_COMMON, // USB Device Sub-class (spec 5.1.1)
        USB_MISC_PROTOCOL_IAD,  // USB Device protocol (spec 5.1.1)
        64,                     // Maximum packet size for default pipe.
        USBShort(0),            // Vendor ID (filled in during USBDCompositeInit).
        USBShort(0),            // Product ID (filled in during USBDCompositeInit).
        USBShort(0x100),        // Device Version BCD.
        1,                      // Manufacturer string identifier.
        2,                      // Product string identifier.
        3,                      // Product serial number.
        1                       // Number of configurations.
    };
    
    //****************************************************************************
    //
    // Composite class device configuration descriptor.
    //
    // It is vital that the configuration descriptor bConfigurationValue field
    // (byte 6) is 1 for the first configuration and increments by 1 for each
    // additional configuration defined here.  This relationship is assumed in the
    // device stack for simplicity even though the USB 2.0 specification imposes
    // no such restriction on the bConfigurationValue values.
    //
    // Note that this structure is deliberately located in RAM since we need to
    // be able to patch some values in it based on client requirements.
    //
    //****************************************************************************
    static const uint8_t g_pui8CompConfigDescriptor[] =
    {
        //
        // Configuration descriptor header.
        //
        9,                          // Size of the configuration descriptor.
        USB_DTYPE_CONFIGURATION,    // Type of this descriptor.
        USBShort(0),                // The total size of this full structure.
        0,                          // The number of interfaces in this
                                    // configuration, this will be filled by
                                    // the class as it discovers all classes
                                    // supported.
        1,                          // The unique value for this configuration.
        0,                          // The string identifier that describes this
                                    // configuration.
        USB_CONF_ATTR_BUS_PWR,      // .
        250,                        // The maximum power in 2mA increments.
    };
    
    //****************************************************************************
    //
    // Byte offsets used to access various fields in our index/interface/endpoint
    // lookup table (tUSBDCompositeDevice.pui32DeviceWorkspace).  This workspace
    // contains one 4 byte entry per device. The LSB is the device index, next byte
    // is the number of the first interface not within this device, next byte is
    // the number of the first IN endpoint not within this device and the final
    // byte is the number of the first OUT endpoint not within this device.  Using
    // this simple table we can reasonably quickly cross-reference index with
    // interface and endpoint numbers.
    //
    //****************************************************************************
    #define LOOKUP_INDEX_BYTE       0
    #define LOOKUP_INTERFACE_BYTE   1
    #define LOOKUP_IN_END_BYTE      2
    #define LOOKUP_OUT_END_BYTE     3
    
    //****************************************************************************
    //
    // A marker used to indicate an invalid index into the device table.
    //
    //****************************************************************************
    #define INVALID_DEVICE_INDEX    0xFFFFFFFF
    
    //****************************************************************************
    //
    // Various internal handlers needed by this class.
    //
    //****************************************************************************
    static void HandleDisconnect(void *pvCompositeInstance);
    static void InterfaceChange(void *pvCompositeInstance, uint8_t ui8InterfaceNum,
                                uint8_t ui8AlternateSetting);
    static void ConfigChangeHandler(void *pvCompositeInstance, uint32_t ui32Value);
    static void DataSent(void *pvCompositeInstance, uint32_t ui32Info);
    static void DataReceived(void *pvCompositeInstance, uint32_t ui32Info);
    static void HandleEndpoints(void *pvCompositeInstance, uint32_t ui32Status);
    static void HandleRequests(void *pvCompositeInstance, tUSBRequest *psUSBRequest);
    static void SuspendHandler(void *pvCompositeInstance);
    static void ResumeHandler(void *pvCompositeInstance);
    static void ResetHandler(void *pvCompositeInstance);
    static void HandleDevice(void *pvCompositeInstance, uint32_t ui32Request,
                             void *pvRequestData);
    static void GetDescriptor(void *pvCompositeInstance, tUSBRequest *psUSBRequest);
    
    //****************************************************************************
    //
    // Configuration Descriptor.
    //
    //****************************************************************************
    tConfigHeader *g_ppCompConfigDescriptors[1];
    
    //****************************************************************************
    //
    // The device information structure for the USB Composite device.
    //
    //****************************************************************************
    const tCustomHandlers g_sCompHandlers =
    {
        //
        // GetDescriptor
        //
        GetDescriptor,
    
        //
        // RequestHandler
        //
        HandleRequests,
    
        //
        // InterfaceChange
        //
        InterfaceChange,
    
        //
        // ConfigChange
        //
        ConfigChangeHandler,
    
        //
        // DataReceived
        //
        DataReceived,
    
        //
        // DataSentCallback
        //
        DataSent,
    
        //
        // ResetHandler
        //
        ResetHandler,
    
        //
        // SuspendHandler
        //
        SuspendHandler,
    
        //
        // ResumeHandler
        //
        ResumeHandler,
    
        //
        // DisconnectHandler
        //
        HandleDisconnect,
    
        //
        // EndpointHandler
        //
        HandleEndpoints,
    
        //
        // DeviceHandler
        //
        HandleDevice,
    };
    
    //****************************************************************************
    //
    // Use the lookup table from the field pui32DeviceWorkspace in the
    // tUSBDCompositeDevice structure to determine which device to call given a
    // particular composite device interface number.
    //
    // The returned value is the index into psDevice->tCompositeEntry indicating
    // the device which contains this interface or INVALID_DEVICE_INDEX if no
    // device contains the passed interface number.
    //
    //****************************************************************************
    static uint32_t
    InterfaceToIndex(tUSBDCompositeDevice *psDevice, uint32_t ui32Interface)
    {
        uint32_t ui32Loop;
        uint32_t ui32Lookup;
    
        //
        // Check each lookup entry in turn.
        //
        for(ui32Loop = 0; ui32Loop < psDevice->ui32NumDevices; ui32Loop++)
        {
            //
            // Get the look up value from the device.
            //
            ui32Lookup = psDevice->psDevices[ui32Loop].ui32DeviceWorkspace;
            ui32Lookup = (ui32Lookup >> (8 * LOOKUP_INTERFACE_BYTE)) & 0xff;
    
            //
            // If the desired interface number is lower than the value in the
            // current lookup table entry, we have found the desired device so
            // return its index.
            //
            if(ui32Interface < ui32Lookup)
            {
                return(ui32Loop);
            }
        }
    
        //
        // If we get here, an invalid interface number was passed so return a
        // marker to indicate this.
        //
        return(INVALID_DEVICE_INDEX);
    }
    
    //****************************************************************************
    //
    // Use the lookup table from the field pui32DeviceWorkspace in the
    // tUSBDCompositeDevice structure to determine which device to call given a
    // particular composite device endpoint number.
    //
    // The returned value is the index into psDevice->tCompositeEntry indicating
    // the device which contains this endpoint or INVALID_DEVICE_INDEX if no
    // device contains the passed endpoint number.
    //
    //****************************************************************************
    static uint32_t
    EndpointToIndex(tUSBDCompositeDevice *psDevice, uint32_t ui32Endpoint,
                    bool bInEndpoint)
    {
        uint32_t ui32Loop, ui32EndpointByte, ui32Lookup;
    
        //
        // Are we considering an IN or OUT endpoint?
        //
        ui32EndpointByte = bInEndpoint ? LOOKUP_IN_END_BYTE : LOOKUP_OUT_END_BYTE;
    
        //
        // Check each lookup entry in turn.
        //
        for(ui32Loop = 0; ui32Loop < psDevice->ui32NumDevices; ui32Loop++)
        {
            //
            // Get the look up byte from the device.
            //
            ui32Lookup = psDevice->psDevices[ui32Loop].ui32DeviceWorkspace;
            ui32Lookup = (ui32Lookup >> (ui32EndpointByte * 8)) & 0xff;
    
            //
            // If the desired endpoint number is lower than the value in the
            // current lookup table entry, we have found the desired device so
            // return its index.
            //
            if(ui32Endpoint < ui32Lookup)
            {
                return(ui32Loop);
            }
        }
    
        //
        // If we get here, an invalid endpoint number was passed so return a
        // marker to indicate this.
        //
        return(INVALID_DEVICE_INDEX);
    }
    
    
    //****************************************************************************
    //
    // This function will check if any device classes need a get descriptor
    // handler called.
    //
    //****************************************************************************
    static void
    GetDescriptor(void *pvCompositeInstance, tUSBRequest *psUSBRequest)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        //
        // Create the composite device pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Determine which device this request is intended for.  We have to be
        // careful here to send this to the callback for the correct device
        // depending upon whether it is a request sent to the device, the interface
        // or the endpoint.
        //
        switch(psUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
        {
            case USB_RTYPE_INTERFACE:
            {
                ui32Idx = InterfaceToIndex(psCompDevice,
                                           (psUSBRequest->wIndex & 0xFF));
                break;
            }
    
            case USB_RTYPE_ENDPOINT:
            {
                ui32Idx = EndpointToIndex(psCompDevice,
                                (psUSBRequest->wIndex & 0x0F),
                                (psUSBRequest->wIndex & 0x80) ? true : false);
                break;
            }
    
            //
            // Requests sent to the device or any other recipient can't be
            // handled here since we have no way of telling where they are
            // supposed to be handled.  As a result, we just stall them.
            //
            // If your composite device has some device-specific descriptors,
            // you should add code here to handle them.
            //
            case USB_RTYPE_DEVICE:
            case USB_RTYPE_OTHER:
            default:
            {
                ui32Idx = INVALID_DEVICE_INDEX;
                break;
            }
        }
    
        //
        // Did we find a device class to pass the request to?
        //
        if(ui32Idx != INVALID_DEVICE_INDEX)
        {
            //
            // Get a pointer to the individual device instance.
            //
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            //
            // Does this device have a GetDescriptor callback?
            //
            if(psDeviceInfo->psCallbacks->pfnGetDescriptor)
            {
                //
                // Remember this device index so that we can correctly route any
                // data notification callbacks to it.
                //
                psCompDevice->sPrivateData.ui32EP0Owner = ui32Idx;
    
                //
                // Call the device to retrieve the descriptor.
                //
                psDeviceInfo->psCallbacks->pfnGetDescriptor(
                   psCompDevice->psDevices[ui32Idx].pvInstance, psUSBRequest);
            }
            else
            {
                //
                // Oops - we can't satisfy the request so stall EP0 to indicate
                // an error.
                //
                USBDCDStallEP0(USBBaseToIndex(
                                  psCompDevice->sPrivateData.ui32USBBase));
            }
        }
        else
        {
            //
            // We are unable to satisfy the descriptor request so stall EP0 to
            // indicate an error.
            //
            USBDCDStallEP0(USBBaseToIndex(
                                  psCompDevice->sPrivateData.ui32USBBase));
        }
    }
    
    //****************************************************************************
    //
    // This function will check if any device classes need an suspend handler
    // called.
    //
    //****************************************************************************
    static void
    SuspendHandler(void *pvCompositeInstance)
    {
        uint32_t ui32Idx;
        tUSBDCompositeDevice *psCompDevice;
        const tDeviceInfo *psDeviceInfo;
        void *pvDeviceInst;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Inform the application that the device has resumed.
        //
        if(psCompDevice->pfnCallback)
        {
            psCompDevice->pfnCallback(pvCompositeInstance, USB_EVENT_SUSPEND,
                                           0, 0);
        }
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
            pvDeviceInst = psCompDevice->psDevices[ui32Idx].pvInstance;
    
            if(psDeviceInfo->psCallbacks->pfnSuspendHandler)
            {
                psDeviceInfo->psCallbacks->pfnSuspendHandler(pvDeviceInst);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function will check if any device classes need an resume handler
    // called.
    //
    //****************************************************************************
    static void
    ResumeHandler(void *pvCompositeInstance)
    {
        uint32_t ui32Idx;
        tUSBDCompositeDevice *psCompDevice;
        const tDeviceInfo *psDeviceInfo;
        void *pvDeviceInst;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Inform the application that the device has resumed.
        //
        if(psCompDevice->pfnCallback)
        {
            psCompDevice->pfnCallback(pvCompositeInstance, USB_EVENT_RESUME,
                                           0, 0);
        }
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
            pvDeviceInst = psCompDevice->psDevices[ui32Idx].pvInstance;
    
            if(psDeviceInfo->psCallbacks->pfnResumeHandler)
            {
                psDeviceInfo->psCallbacks->pfnResumeHandler(pvDeviceInst);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function will check if any device classes need an reset handler
    // called.
    //
    //****************************************************************************
    static void
    ResetHandler(void *pvCompositeInstance)
    {
        uint32_t ui32Idx;
        tUSBDCompositeDevice *psCompDevice;
        const tDeviceInfo *psDeviceInfo;
        void *pvDeviceInst;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Inform the application that the device has been connected.
        //
        if(psCompDevice->pfnCallback)
        {
            psCompDevice->pfnCallback(pvCompositeInstance,
                                           USB_EVENT_CONNECTED, 0, 0);
        }
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
            pvDeviceInst = psCompDevice->psDevices[ui32Idx].pvInstance;
    
            if(psDeviceInfo->psCallbacks->pfnResetHandler)
            {
                psDeviceInfo->psCallbacks->pfnResetHandler(pvDeviceInst);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called to handle data being set to the host so that the
    // application callback can be called when the data has been transferred.
    //
    //****************************************************************************
    static void
    DataSent(void *pvCompositeInstance, uint32_t ui32Info)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Pass this notification on to the device which last handled a
        // transaction on endpoint 0 (assuming we know who that was).
        //
        ui32Idx = psCompDevice->sPrivateData.ui32EP0Owner;
    
        if(ui32Idx != INVALID_DEVICE_INDEX)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnDataSent)
            {
                psDeviceInfo->psCallbacks->pfnDataSent(
                    psCompDevice->psDevices[ui32Idx].pvInstance, ui32Info);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called to handle data being received back from the host so
    // that the application callback can be called when the new data is ready.
    //
    //****************************************************************************
    static void
    DataReceived(void *pvCompositeInstance, uint32_t ui32Info)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Pass this notification on to the device which last handled a
        // transaction on endpoint 0 (assuming we know who that was).
        //
        ui32Idx = psCompDevice->sPrivateData.ui32EP0Owner;
    
        if(ui32Idx != INVALID_DEVICE_INDEX)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnDataReceived)
            {
                psDeviceInfo->psCallbacks->pfnDataReceived(
                    psCompDevice->psDevices[ui32Idx].pvInstance, ui32Info);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function will check if any device classes need an endpoint handler
    // called.
    //
    //****************************************************************************
    static void
    HandleEndpoints(void *pvCompositeInstance, uint32_t ui32Status)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Call each of the endpoint handlers.  This may seem odd since we should
        // only call the handler whose endpoint needs service.  Unfortunately, if
        // the device class driver is using uDMA, we have no way of knowing which
        // handler to call (since ui32Status will be 0).  Since the handlers are
        // set up to ignore any callback that is not for them, this is safe.
        //
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnEndpointHandler)
            {
                psDeviceInfo->psCallbacks->pfnEndpointHandler(
                    psCompDevice->psDevices[ui32Idx].pvInstance, ui32Status);
            }
        }
    }
    
    //*****************************************************************************
    //
    // Device instance specific handler.
    //
    //*****************************************************************************
    static void
    HandleDevice(void *pvCompositeInstance, uint32_t ui32Request,
                 void *pvRequestData)
    {
        uint32_t ui32Idx;
        tUSBDCompositeDevice *psCompDevice;
        const tDeviceInfo *psDeviceInfo;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnDeviceHandler)
            {
                psDeviceInfo->psCallbacks->pfnDeviceHandler(
                    psCompDevice->psDevices[ui32Idx].pvInstance, ui32Request,
                    pvRequestData);
            }
        }
    
        if(psCompDevice->pfnCallback)
        {
            switch(ui32Request)
            {
                case USB_EVENT_LPM_RESUME:
                {
                    //
                    // Pass the LPM resume event to the client.
                    //
                    psCompDevice->pfnCallback(0, USB_EVENT_LPM_RESUME, 0,
                                                   (void *)0);
                    break;
                }
                case USB_EVENT_LPM_SLEEP:
                {
                    //
                    // Pass the LPM sleep event to the client.
                    //
                    psCompDevice->pfnCallback(0, USB_EVENT_LPM_SLEEP, 0,
                                                   (void *)0);
                    break;
                }
                case USB_EVENT_LPM_ERROR:
                {
                    //
                    // Pass the LPM error event to the client.
                    //
                    psCompDevice->pfnCallback(0, USB_EVENT_LPM_ERROR, 0,
                                                   (void *)0);
                    break;
                }
                default:
                {
                    break;
                }
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called by the USB device stack whenever the device is
    // disconnected from the host.
    //
    //****************************************************************************
    static void
    HandleDisconnect(void *pvCompositeInstance)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Inform the application that the device has been disconnected.
        //
        if(psCompDevice->pfnCallback)
        {
            psCompDevice->pfnCallback(pvCompositeInstance,
                                           USB_EVENT_DISCONNECTED, 0, 0);
        }
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnDisconnectHandler)
            {
                psDeviceInfo->psCallbacks->pfnDisconnectHandler(
                    psCompDevice->psDevices[ui32Idx].pvInstance);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called by the USB device stack whenever the device
    // interface changes.  It will be passed on to the device classes if they have
    // a handler for this function.
    //
    //****************************************************************************
    static void
    InterfaceChange(void *pvCompositeInstance, uint8_t ui8InterfaceNum,
                    uint8_t ui8AlternateSetting)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnInterfaceChange)
            {
                psDeviceInfo->psCallbacks->pfnInterfaceChange(
                    psCompDevice->psDevices[ui32Idx].pvInstance,
                    ui8InterfaceNum, ui8AlternateSetting);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called by the USB device stack whenever the device
    // configuration changes. It will be passed on to the device classes if they
    // have a handler for this function.
    //
    //****************************************************************************
    static void
    ConfigChangeHandler(void *pvCompositeInstance, uint32_t ui32Value)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        ASSERT(pvCompositeInstance != 0);
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Inform the application that the device configuration has changed.
        //
        if(psCompDevice->pfnCallback)
        {
            psCompDevice->pfnCallback(pvCompositeInstance, USB_EVENT_CONFIG_CHANGE,
                                      ui32Value, 0);
        }
    
        for(ui32Idx = 0; ui32Idx < psCompDevice->ui32NumDevices; ui32Idx++)
        {
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            if(psDeviceInfo->psCallbacks->pfnConfigChange)
            {
                psDeviceInfo->psCallbacks->pfnConfigChange(
                    psCompDevice->psDevices[ui32Idx].pvInstance, ui32Value);
            }
        }
    }
    
    //****************************************************************************
    //
    // This function is called by the USB device stack whenever a non-standard
    // request is received.
    //
    // \param pvCompositeInstance
    // \param psUSBRequest points to the request received.
    //
    // This call  will be passed on to the device classes if they have a handler
    // for this function.
    //
    // \return None.
    //
    //****************************************************************************
    static void
    HandleRequests(void *pvCompositeInstance, tUSBRequest *psUSBRequest)
    {
        uint32_t ui32Idx;
        const tDeviceInfo *psDeviceInfo;
        tUSBDCompositeDevice *psCompDevice;
    
        //
        // Create the device instance pointer.
        //
        psCompDevice = (tUSBDCompositeDevice *)pvCompositeInstance;
    
        //
        // Determine which device this request is intended for.  We have to be
        // careful here to send this to the callback for the correct device
        // depending upon whether it is a request sent to the device, the interface
        // or the endpoint.
        //
        switch(psUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
        {
            case USB_RTYPE_INTERFACE:
            {
                ui32Idx = InterfaceToIndex(psCompDevice,
                                           (psUSBRequest->wIndex & 0xFF));
                break;
            }
    
            case USB_RTYPE_ENDPOINT:
            {
                ui32Idx = EndpointToIndex(psCompDevice,
                                 (psUSBRequest->wIndex & 0x0F),
                                 (psUSBRequest->wIndex & 0x80) ? true : false);
                break;
            }
    
            //
            // Requests sent to the device or any other recipient can't be
            // handled here since we have no way of telling where they are
            // supposed to be handled.  As a result, we just stall them.
            //
            // If your composite device has some device-specific requests that need
            // to be handled at the device (rather than interface or endpoint)
            // level, you should add code here to handle them.
            //
            case USB_RTYPE_DEVICE:
            case USB_RTYPE_OTHER:
            default:
            {
                ui32Idx = INVALID_DEVICE_INDEX;
                break;
            }
        }
    
        //
        // Did we find a device class to pass the request to?
        //
        if(ui32Idx != INVALID_DEVICE_INDEX)
        {
            //
            // Get a pointer to the individual device instance.
            //
            psDeviceInfo = psCompDevice->psDevices[ui32Idx].psDevInfo;
    
            //
            // Does this device have a RequestHandler callback?
            //
            if(psDeviceInfo->psCallbacks->pfnRequestHandler)
            {
                //
                // Remember this device index so that we can correctly route any
                // data notification callbacks to it.
                //
                psCompDevice->sPrivateData.ui32EP0Owner = ui32Idx;
    
                //
                // Yes - call the device to retrieve the descriptor.
                //
                psDeviceInfo->psCallbacks->pfnRequestHandler(
                        psCompDevice->psDevices[ui32Idx].pvInstance,
                        psUSBRequest);
            }
            else
            {
                //
                // Oops - we can't satisfy the request so stall EP0 to indicate
                // an error.
                //
                USBDCDStallEP0(USBBaseToIndex(
                                  psCompDevice->sPrivateData.ui32USBBase));
            }
        }
        else
        {
            //
            // We are unable to satisfy the descriptor request so stall EP0 to
            // indicate an error.
            //
            USBDCDStallEP0(USBBaseToIndex(
                                  psCompDevice->sPrivateData.ui32USBBase));
        }
    }
    
    //****************************************************************************
    //
    // This function handles sending interface number changes to device instances.
    //
    //****************************************************************************
    static void
    CompositeIfaceChange(tCompositeEntry *psCompDevice, uint8_t ui8Old,
                         uint8_t ui8New)
    {
        uint8_t pui8Interfaces[2];
    
        if(psCompDevice->psDevInfo->psCallbacks->pfnDeviceHandler)
        {
            //
            // Create the data to pass to the device handler.
            //
            pui8Interfaces[0] = ui8Old;
            pui8Interfaces[1] = ui8New;
    
            //
            // Call the device handler to inform the class of the interface number
            // change.
            //
            psCompDevice->psDevInfo->psCallbacks->pfnDeviceHandler(
                psCompDevice->pvInstance, USB_EVENT_COMP_IFACE_CHANGE,
                (void *)pui8Interfaces);
        }
    }
    
    //****************************************************************************
    //
    // This function handles sending endpoint number changes to device instances.
    //
    //****************************************************************************
    static void
    CompositeEPChange(tCompositeEntry *psCompDevice, uint8_t ui8Old,
                         uint8_t ui8New)
    {
        uint8_t pui8Interfaces[2];
    
        if(psCompDevice->psDevInfo->psCallbacks->pfnDeviceHandler)
        {
            //
            // Create the data to pass to the device handler.
            //
            pui8Interfaces[0] = ui8Old;
            pui8Interfaces[1] = ui8New;
    
            ui8New--;
    
            //
            // Call the device handler to inform the class of the interface number
            // change.
            //
            psCompDevice->psDevInfo->psCallbacks->pfnDeviceHandler(
                psCompDevice->pvInstance, USB_EVENT_COMP_EP_CHANGE,
                (void *)pui8Interfaces);
        }
    }
    
    //****************************************************************************
    //
    // This function merges the configuration descriptors into a single multiple
    // instance device.
    //
    //****************************************************************************
    uint32_t
    BuildCompositeDescriptor(tUSBDCompositeDevice *psCompDevice)
    {
        uint32_t ui32Idx, ui32Offset, ui32CPIdx, ui32FixINT, ui32Dev;
        uint16_t ui16TotalLength, ui16Bytes;
        uint8_t ui8Interface, ui8INEndpoint, ui8OUTEndpoint;
        uint8_t *pui8Data, *pui8Config;
        const tConfigHeader *psConfigHeader;
        tDescriptorHeader *psHeader;
        const uint8_t *pui8Descriptor;
        tInterfaceDescriptor *psInterface;
        tEndpointDescriptor *psEndpoint;
        const tDeviceInfo *psDevice;
    
        //
        // Save the number of devices to look through.
        //
        ui32Dev = 0;
        ui32Idx = 0;
        ui8Interface = 0;
        ui8INEndpoint = 1;
        ui8OUTEndpoint = 1;
        ui32Offset = 0;
        ui32FixINT = 0;
    
        //
        // This puts the first section pointer in the first entry in the list
        // of sections.
        //
        psCompDevice->sPrivateData.ppsCompSections[0] =
            &psCompDevice->sPrivateData.psCompSections[0];
    
        //
        // Put the pointer to this instances configuration descriptor into the
        // front of the list.
        //
        psCompDevice->sPrivateData.ppsCompSections[0]->pui8Data =
            (uint8_t *)&psCompDevice->sPrivateData.sConfigDescriptor;
    
        psCompDevice->sPrivateData.ppsCompSections[0]->ui16Size =
            psCompDevice->sPrivateData.sConfigDescriptor.bLength;
    
        //
        // The configuration descriptor is 9 bytes so initialize the total length
        // to 9 bytes.
        //
        ui16TotalLength = 9;
    
        //
        // Copy the section pointer into the section array for the composite
        // device.  This is awkward but is required given the definition
        // of the structures.
        //
        psCompDevice->sPrivateData.ppsCompSections[1] =
            &psCompDevice->sPrivateData.psCompSections[1];
    
        //
        // Copy the pointer to the application supplied space into the section
        // list.
        //
        psCompDevice->sPrivateData.ppsCompSections[1]->ui16Size = 0;
        psCompDevice->sPrivateData.ppsCompSections[1]->pui8Data =
            psCompDevice->sPrivateData.pui8Data;
    
        //
        // Create a local pointer to the data that is used to copy data from
        // the other devices into the composite descriptor.
        //
        pui8Data = psCompDevice->sPrivateData.pui8Data;
    
        //
        // Consider each device in turn.
        //
        while(ui32Dev < psCompDevice->ui32NumDevices)
        {
            //
            // Save the current starting address of this descriptor.
            //
            pui8Config = pui8Data + ui32Offset;
    
            //
            // Create a local pointer to the configuration header.
            //
            psDevice = psCompDevice->psDevices[ui32Dev].psDevInfo;
            psConfigHeader = psDevice->ppsConfigDescriptors[0];
    
            //
            // Loop through each of the sections in this device's configuration
            // descriptor.
            //
            for(ui32Idx = 0; ui32Idx < psConfigHeader->ui8NumSections; ui32Idx++)
            {
                //
                // Initialize the local offset in this descriptor.  We include
                // a special case here to ignore the initial 9 byte configuration
                // descriptor since this has already been handled.
                //
                if(ui32Idx)
                {
                    //
                    // This is not the first section so we handle everything in
                    // it.
                    //
                    ui16Bytes = 0;
                }
                else
                {
                    //
                    // This is the first section for this device so skip the 9
                    // byte configuration descriptor since we've already handled
                    // this.
                    //
                    ui16Bytes = 9;
    
                    //
                    // If this section includes only the configuration descriptor,
                    // skip it entirely.
                    //
                    if(psConfigHeader->psSections[ui32Idx]->ui16Size <= ui16Bytes)
                    {
                        continue;
                    }
                }
    
                //
                // Get a pointer to the configuration descriptor.
                //
                pui8Descriptor = psConfigHeader->psSections[ui32Idx]->pui8Data;
    
                //
                // Bounds check the allocated space and return if there is not
                // enough space.
                //
                if(ui32Offset > psCompDevice->sPrivateData.ui32DataSize)
                {
                    return(1);
                }
    
                //
                // Copy the descriptor from the device into the descriptor list.
                //
                for(ui32CPIdx = 0;
                    ui32CPIdx < psConfigHeader->psSections[ui32Idx]->ui16Size;
                    ui32CPIdx++)
                {
                    pui8Data[ui32CPIdx + ui32Offset] = pui8Descriptor[ui32CPIdx];
                }
    
                //
                // Read out the descriptors in this section.
                //
                while(ui16Bytes < psConfigHeader->psSections[ui32Idx]->ui16Size)
                {
                    //
                    // Create a descriptor header pointer.
                    //
                    psHeader = (tDescriptorHeader *)&pui8Data[ui32Offset +
                                                              ui16Bytes];
    
                    //
                    // Check for interface descriptors and modify the numbering to
                    // match the composite device.
                    //
                    if(psHeader->bDescriptorType == USB_DTYPE_INTERFACE)
                    {
                        psInterface = (tInterfaceDescriptor *)psHeader;
    
                        //
                        // See if this is an alternate setting or the initial
                        // setting.
                        //
                        if(psInterface->bAlternateSetting != 0)
                        {
                            //
                            // If this is an alternate setting then use the
                            // previous interface number because the current one
                            // has already been incremented.
                            //
                            psInterface->bInterfaceNumber = ui8Interface - 1;
                        }
                        else
                        {
                            //
                            // Notify the class that it's interface number has
                            // changed.
                            //
                            CompositeIfaceChange(
                                             &psCompDevice->psDevices[ui32Dev],
                                             psInterface->bInterfaceNumber,
                                             ui8Interface);
                            //
                            // This was the non-alternate setting so save the
                            // value and move to the next interface number.
                            //
                            psInterface->bInterfaceNumber = ui8Interface;
    
                            //
                            // No strings allowed on interface descriptors for
                            // composite devices.
                            //
                            psInterface->iInterface = 0;
    
                            ui8Interface++;
                        }
                    }
                    //
                    // Check for endpoint descriptors and modify the numbering to
                    // match the composite device.
                    //
                    else if(psHeader->bDescriptorType == USB_DTYPE_ENDPOINT)
                    {
                        psEndpoint = (tEndpointDescriptor *)psHeader;
    
                        //
                        // Check if this is an IN or OUT endpoint.
                        //
                        if(psEndpoint->bEndpointAddress & USB_RTYPE_DIR_IN)
                        {
                            //
                            // Check if this is the special Fixed Interrupt class
                            // and this is the interrupt endpoint.
                            //
    //                        if(((psEndpoint->bmAttributes & USB_EP_ATTR_TYPE_M) ==
    //                            USB_EP_ATTR_INT) &&
    //                           (psCompDevice->ui16PID == USB_PID_COMP_SERIAL))
    //                        {
    //                            //
    //                            // Check if the Fixed Interrupt endpoint has been
    //                            // set yet.
    //                            //
    //                            if(ui32FixINT == 0)
    //                            {
    //                                //
    //                                // Allocate the fixed interrupt endpoint and
    //                                // save its number.
    //                                //
    //                                ui32FixINT = ui8INEndpoint++;
    //                            }
    //
    //                            CompositeEPChange(
    //                                        &psCompDevice->psDevices[ui32Dev],
    //                                        psEndpoint->bEndpointAddress,
    //                                        ui32FixINT);
    //
    //                            psEndpoint->bEndpointAddress = ui32FixINT |
    //                                                           USB_RTYPE_DIR_IN;
    //                        }
    //                        else
    //                        {
                                //
                                // Notify the class that it's interface number has
                                // changed.
                                //
                                CompositeEPChange(
                                            &psCompDevice->psDevices[ui32Dev],
                                            psEndpoint->bEndpointAddress,
                                            ui8INEndpoint);
    
                                psEndpoint->bEndpointAddress = ui8INEndpoint++ |
                                                               USB_RTYPE_DIR_IN;
    //                        }
                        }
                        else
                        {
                            //
                            // Notify the class that it's interface number has
                            // changed.
                            //
                            CompositeEPChange(&psCompDevice->psDevices[ui32Dev],
                                              psEndpoint->bEndpointAddress,
                                              ui8OUTEndpoint);
                            psEndpoint->bEndpointAddress = ui8OUTEndpoint++;
                        }
                    }
    
                    //
                    // Move on to the next descriptor.
                    //
                    ui16Bytes += psHeader->bLength;
                }
    
                ui32Offset += psConfigHeader->psSections[ui32Idx]->ui16Size;
    
                ui16TotalLength += ui16Bytes;
            }
    
            //
            // Allow the device class to make adjustments to the configuration
            // descriptor.
            //
            psCompDevice->psDevices[ui32Dev].psDevInfo->psCallbacks->pfnDeviceHandler(
                    psCompDevice->psDevices[ui32Dev].pvInstance,
                    USB_EVENT_COMP_CONFIG, (void *)pui8Config);
    
            //
            // Add an entry into the device workspace array to allow us to quickly
            // map interface and endpoint numbers to device instances later.
            //
            psCompDevice->psDevices[ui32Dev].ui32DeviceWorkspace =
                (ui32Dev << (LOOKUP_INDEX_BYTE * 8)) |
                (ui8Interface << (LOOKUP_INTERFACE_BYTE * 8)) |
                (ui8OUTEndpoint << (LOOKUP_OUT_END_BYTE * 8)) |
                (ui8INEndpoint << (LOOKUP_IN_END_BYTE * 8));
    
            //
            // Move on to the next device.
            //
            ui32Dev++;
        }
    
        //
        // Modify the configuration descriptor to match the number of interfaces
        // and the new total size.
        //
        psCompDevice->sPrivateData.sCompConfigHeader.ui8NumSections = 2;
        psCompDevice->sPrivateData.ppsCompSections[1]->ui16Size = ui32Offset;
        psCompDevice->sPrivateData.sConfigDescriptor.bNumInterfaces =
           ui8Interface;
        psCompDevice->sPrivateData.sConfigDescriptor.wTotalLength =
           ui16TotalLength;
    
    
        return(0);
    }
    
    //****************************************************************************
    //
    //! This function should be called once for the composite class device to
    //! initialize basic operation and prepare for enumeration.
    //!
    //! \param ui32Index is the index of the USB controller to initialize for
    //! composite device operation.
    //! \param psDevice points to a structure containing parameters customizing
    //! the operation of the composite device.
    //! \param ui32Size is the size in bytes of the data pointed to by the
    //! \e pui8Data parameter.
    //! \param pui8Data is the data area that the composite class can use to build
    //! up descriptors.
    //!
    //! In order for an application to initialize the USB composite device class,
    //! it must first call this function with the a valid composite device class
    //! structure in the \e psDevice parameter.  This allows this function to
    //! initialize the USB controller and device code to be prepared to enumerate
    //! and function as a USB composite device.  The \e ui32Size and \e pui8Data
    //! parameters should be large enough to hold all of the class instances
    //! passed in via the \e psDevice structure.  This is typically the full size
    //! of the configuration descriptor for a device minus its configuration
    //! header(9 bytes).
    //!
    //! This function returns a void pointer that must be passed in to all other
    //! APIs used by the composite class.
    //!
    //! See the documentation on the tUSBDCompositeDevice structure for more
    //! information on how to properly fill the structure members.
    //!
    //! \return This function returns 0 on failure or a non-zero void pointer on
    //! success.
    //
    //****************************************************************************
    void *
    USBDCompositeInit(uint32_t ui32Index, tUSBDCompositeDevice *psDevice,
                      uint32_t ui32Size, uint8_t *pui8Data)
    {
        tCompositeInstance *psInst;
        int32_t i32Idx;
        uint8_t *pui8Temp;
    
        //
        // Check parameter validity.
        //
        ASSERT(ui32Index == 0);
        ASSERT(psDevice);
        ASSERT(psDevice->ppui8StringDescriptors);
    
        //
        // Initialize the work space in the passed instance structure.
        //
        psInst = &psDevice->sPrivateData;
        psInst->ui32DataSize = ui32Size;
        psInst->pui8Data = pui8Data;
    
        //
        // Save the base address of the USB controller.
        //
        psInst->ui32USBBase = USBIndexToBase(ui32Index);
    
        //
        // No device is currently transferring data on EP0.
        //
        psInst->ui32EP0Owner = INVALID_DEVICE_INDEX;
    
        //
        // Initialize the device information structure.
        //
        psInst->sDevInfo.psCallbacks = &g_sCompHandlers;
        psInst->sDevInfo.pui8DeviceDescriptor = g_pui8CompDeviceDescriptor;
        psInst->sDevInfo.ppsConfigDescriptors =
                        (const tConfigHeader * const *)g_ppCompConfigDescriptors;
        psInst->sDevInfo.ppui8StringDescriptors = 0;
        psInst->sDevInfo.ui32NumStringDescriptors = 0;
    
        //
        // Initialize the device info structure for the composite device.
        //
        USBDCDDeviceInfoInit(0, &psInst->sDevInfo);
    
        g_ppCompConfigDescriptors[0] = &psInst->sCompConfigHeader;
        g_ppCompConfigDescriptors[0]->ui8NumSections = 0;
        g_ppCompConfigDescriptors[0]->psSections =
          (const tConfigSection * const *)psDevice->sPrivateData.ppsCompSections;
    
        //
        // Create a byte pointer to use with the copy.
        //
        pui8Temp = (uint8_t *)&psInst->sConfigDescriptor;
    
        //
        // Copy the default configuration descriptor into the instance data.
        //
        for(i32Idx = 0; i32Idx < g_pui8CompConfigDescriptor[0]; i32Idx++)
        {
            pui8Temp[i32Idx] = g_pui8CompConfigDescriptor[i32Idx];
        }
    
        //
        // Create a byte pointer to use with the copy.
        //
        pui8Temp = (uint8_t *)&psInst->sDeviceDescriptor;
    
        //
        // Copy the default configuration descriptor into the instance data.
        //
        for(i32Idx = 0; i32Idx < g_pui8CompDeviceDescriptor[0]; i32Idx++)
        {
            pui8Temp[i32Idx] = g_pui8CompDeviceDescriptor[i32Idx];
        }
    
        //
        // Fix up the device descriptor with the client-supplied values.
        //
        psInst->sDeviceDescriptor.idVendor = psDevice->ui16VID;
        psInst->sDeviceDescriptor.idProduct = psDevice->ui16PID;
    
        //
        // Fix up the configuration descriptor with client-supplied values.
        //
        psInst->sConfigDescriptor.bmAttributes = psDevice->ui8PwrAttributes;
        psInst->sConfigDescriptor.bMaxPower =
            (uint8_t)(psDevice->ui16MaxPowermA>>1);
    
        psInst->sDevInfo.pui8DeviceDescriptor =
                                    (const uint8_t *)&psInst->sDeviceDescriptor;
    
        //
        // Plug in the client's string table to the device information
        // structure.
        //
        psInst->sDevInfo.ppui8StringDescriptors =
                                                psDevice->ppui8StringDescriptors;
        psInst->sDevInfo.ui32NumStringDescriptors =
                                                psDevice->ui32NumStringDescriptors;
    
        //
        // Enable Clocking to the USB controller so that changes to the USB
        // controller can be made in the BuildCompositeDescriptor() function.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
    
        //
        // Create the combined descriptors.
        //
        if(BuildCompositeDescriptor(psDevice))
        {
            return(0);
        }
    
        //
        // All is well so now pass the descriptors to the lower layer and put
        // the bulk device on the bus.
        //
        USBDCDInit(ui32Index, &psInst->sDevInfo, (void *)psDevice);
    
        //
        // Return the pointer to the instance indicating that everything went
        // well.
        //
        return((void *)psDevice);
    }
    
    //****************************************************************************
    //
    //! Shuts down the composite device.
    //!
    //! \param pvCompositeInstance is the pointer to the device instance structure
    //! as returned by USBDCompositeInit().
    //!
    //! This function terminates composite device interface for the instance
    //! not me supplied. Following this call, the \e pvCompositeInstance instance
    //! should not be used in any other calls.
    //!
    //! \return None.
    //
    //****************************************************************************
    void
    USBDCompositeTerm(void *pvCompositeInstance)
    {
        ASSERT(pvCompositeInstance != 0);
    
    }
    
    //****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //****************************************************************************
    
    

    EDIT: The above solution has not proven to work for all users. Please try it first but if the issue persists continue to monitor this thread. The composite device issue is being actively looked into and this thread will be updated when a final solution is reached.

  • Hello Ralph Jacobi,

    Thanks for the reply. Is it possible to explain it in bit more detail? We have done some project specific changes in all .c files. So I cannot replace usbdcomp.c as it is in my code. Even comparison seems to be harder with this file.
    Also I cannot replace the windows_driver folder with SW-TM4C-2.1.4.178.PATCH-1.0/windows_drivers as we have changed tidfu.cpp.

    Best regards
    Harsh
  • Just a reminder that we are using TMS320F28069UPFPS controller and the fix suggested is in TM4C forum. So will it work with our controller.
  • Hello Harsh,

    I can explain the .c file changes, but I was not involved in the Windows Driver changes so I can't comment on that.

    Furthermore, I have no idea if these will help with the TMS320F28069 - that is a C2000 processor so that isn't supported by TivaWare...

    For the usbdcomp.c file, there is an if statement that shares endpoint identifiers and that was causing the issue on Win 10.

    The if statement starts with this snippet:

    if(((psEndpoint->bmAttributes & USB_EP_ATTR_TYPE_M) ==
                                USB_EP_ATTR_INT) &&
                               (psCompDevice->ui16PID == USB_PID_COMP_SERIAL))

    The commented lines are from line 1259 to line 1285, and line 1297.