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 Host CDC Examples or Suggestions?

Other Parts Discussed in Thread: CC3200

I'm currently developing  a USB Host CDC for the TM4C123 and am hoping to find some examples or get some suggestions on how best to approach this.

The USB Device I need to host is using the Microchip USB Stack and becomes a virtual serial port under Windows as the USB Endpoint is an ACM (Abstract Control Model) USB subclass.

I have seen the example developed by Leo Hendrawan - http://processors.wiki.ti.com/index.php/Stellaris_-_USB_Host_FTDI

But this is for a device with an FTDI chip, I am assuming this code can be worked on, but have not been able to work out where to start.

Any and all suggestions welcome!

  • I should mention I have read the TivaWare USB Library User Guide. And although it goes into extensive detail regarding Device CDC, it does not mention Host CDC once.

    So where should I start? I can see that utilising USB Host Controller Driver for a few things , but will I need to also work directly with the USB DriverLib API?

    Anyway, I was hoping that for such a common USB class there would have been a few more higher level APIs available.

  • Ok...my request seems to be a relatively common one. Here are just a few posts.....

    http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/t/146915.aspx

    http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/t/45178.aspx

    http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/p/45125/161395.aspx

    http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/p/127237/455567.aspx#455567

    Are there any technical reasons that a Host CDC ACM example hasn't been developed after all these requests?

    I'm giving it a go, but I'd hate to waste time on something that wasn't technically feasible!

  • Hi Glen.  Did you have any luck getting this working?  I'm looking for the same kind of thing.

  • Hi Allan,

    You are in luck, I did get most of it working. I only required sending data out my USB port, so you will need to work on it to get data in, but that should be relatively simple once the enumeration takes place. My code is custom, so you may need to play around with it a bit to get enumeration working, as it depends on how your CDC device has set up its interfaces and endpoints. CDC devices can vary in this setup.

    If you are only starting out with USB embedded host work, I suggest the following resources.

    * USB in a Nutshell - http://www.beyondlogic.org/usbnutshell/usb1.shtml
    * USB Embedded Hosts - http://www.amazon.com/USB-Embedded-Hosts-Developers-Guide/dp/1931448248
    * USBlyzer - http://www.usblyzer.com/ - Great tool to look at how your USB device enumarates, how it has setup its interfaces and endpoints.
    * A USB Protocol Analyzer - http://www.totalphase.com/ - If you can afford it, this will help you a lot. Wish I had one!

    I have attached the CDC driver code, which you should be able to adapt to your uses. I have also attached the usbhostenum.c which is one the main usb host library that comes with Tivaware. I needed to make some changes to this code, as I discovered a few bugs. I don't believe TI has got around to resolving these yet. The bugs are discussed here - http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/296947.aspx

    //*****************************************************************************
    //
    // usbhcdc.c - USB Communications Device Class host driver.
    //
    //
    //
    //*****************************************************************************
    
    #include <string.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/usb.h"
    #include "usblib/usblib.h"
    #include "usblib/usblibpriv.h"
    #include "usblib/host/usbhost.h"
    #include "usblib/host/usbhostpriv.h"
    #include "usblib/host/usbhcdc.h"
    #include "usblib/host/usbhscsi.h"
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/Memory.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/gates/GateMutex.h>
    #include <ti/sysbios/hal/Hwi.h>
    #include <ti/sysbios/hal/Timer.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Swi.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Queue.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/WiFi.h>
    
    
    //*****************************************************************************
    //
    //! \addtogroup usblib_host_class
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Forward declarations for the driver open and close calls.
    //
    //*****************************************************************************
    static void *USBHCDCOpen(tUSBHostDevice *psDevice);
    static void USBHCDCClose(void *pvInstance);
    
    //*****************************************************************************
    //
    // This is the structure for an instance of a USB CDC host driver.
    //
    //*****************************************************************************
    struct tUSBHCDCInstance
    {
        //
        // Save the device instance.
        //
        tUSBHostDevice *psDevice;
    
        //
        // Used to save the callback.
        //
        tUSBHCDCCallback pfnCallback;
    
        //
        // This is the control interface.
        //
        uint8_t ui8IControl;
    
        //
        // Interrupt IN pipe.
        //
        uint32_t ui32IntInPipe;
    
        //
        // Bulk IN pipe.
        //
        uint32_t ui32BulkInPipe;
    
        //
        // Bulk OUT pipe.
        //
        uint32_t ui32BulkOutPipe;
    };
    
    
    //
    // Line Coding Information Structure
    //
    struct tLineCoding
    {
        long   dwDTERate;	// Data Terminal Rate in bits per second
        short  bCharFormat;	// 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
        short  bParityType;	// 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
        short  bDataBits;	// Data bits (5, 6, 7, 8 or 16)
    };
    
    //
    // Line Status Information Structure
    //
    struct tLineStatus
    {
        long wLength;	    // Size of this structure in bytes
        long dwRingerBitmap;  // Ringer Configuration bitmap for this line.
        long dwLineState;	    // Defines current state of the line.
        long dwCallState;	    // Defines current state of first call on the line.
    };
    
    //*****************************************************************************
    //
    // The array of USB CDC host drivers.
    //
    //*****************************************************************************
    static tUSBHCDCInstance g_USBHCDCDevice =
    {
        0
    };
    
    //*****************************************************************************
    //
    //! This constant global structure defines the CDC Driver that
    //! is provided with the USB library.
    //
    //*****************************************************************************
    const tUSBHostClassDriver g_sUSBHostCDCClassDriver =
    {
    	USB_CLASS_CDC,
        USBHCDCOpen,
        USBHCDCClose,
        0
    };
    
    //*****************************************************************************
    //
    // This function handles callbacks for the Bulk IN endpoint.
    //
    //*****************************************************************************
    unsigned char SchedulePipeInBuffer[64];
    static void USBHCDCINCallback(uint32_t ulPipe, uint32_t ulEvent)
    {
            uint32_t ulSize;
            //
            // Handles a request to schedule a new request on the interrupt IN
            // pipe.
            //
            if(ulEvent == USB_EVENT_SCHEDULER)
            {
                USBHCDPipeSchedule(ulPipe, SchedulePipeInBuffer, 64);
            }
    
            //
            // Called when new data is available on the interrupt IN pipe.
            //
            if(ulEvent == USB_EVENT_RX_AVAILABLE)
            {
                  //
                  // If the callback exists then call it.
                  //
                  if(g_USBHCDCDevice.pfnCallback != 0)
                  {
                      memset(SchedulePipeInBuffer,0,64);
                      //
                      // Read the Data out.
                      //
                      ulSize = USBHCDPipeReadNonBlocking(ulPipe, SchedulePipeInBuffer,
                                                     64);
                      //
                      // Call
                      //
    
                      g_USBHCDCDevice.pfnCallback(&g_USBHCDCDevice,
                                                  CDC_EVENT_RX_AVAILABLE,
                                                  (void*)SchedulePipeInBuffer,
                                                  ulSize);
                      //
                      // Schedule another read
                      //
                      USBHCDPipeSchedule(ulPipe, SchedulePipeInBuffer, 64);
                  }
            }
    }
    
    //*****************************************************************************
    //
    // This function handles callbacks for the Interrupt IN endpoint.
    //
    //*****************************************************************************
    unsigned char SchedulePipeInterruptBuffer[100];
    
    static void USBHCDCInterruptCallback(uint32_t ulPipe, uint32_t ulEvent)
    {
            uint32_t ulSize;
            //
            // Handles a request to schedule a new request on the interrupt IN
            // pipe.
            //
            if(ulEvent == USB_EVENT_SCHEDULER)
            {
                USBHCDPipeSchedule(ulPipe, SchedulePipeInterruptBuffer, 100);
            }
    
            //
            // Called when new data is available on the interrupt IN pipe.
            //
            if(ulEvent == USB_EVENT_RX_AVAILABLE)
            {
                  //
                  // If the callback exists then call it.
                  //
                  if(g_USBHCDCDevice.pfnCallback != 0)
                  {
                      //
                      // Read the Data out.
                      //
                      ulSize = USBHCDPipeReadNonBlocking(ulPipe, SchedulePipeInterruptBuffer,
                                                     100);
                      //
                      // Call
                      //
                      g_USBHCDCDevice.pfnCallback(&g_USBHCDCDevice,
                                                  CDC_EVENT_INTERRUPT,
                                                  (void*)SchedulePipeInterruptBuffer,
                                                  ulSize);
    
    
                      //
                      // Schedule another read
                      //
                      USBHCDPipeSchedule(ulPipe, SchedulePipeInterruptBuffer, 100);
    
                      //UARTprintf("USBHCDCInterruptCallback\n\r");
                  }
            }
    }
    
    //*****************************************************************************
    //
    // This function handles callbacks for the interrupt IN endpoint.
    //
    //*****************************************************************************
    //static void
    //HIDIntINCallback(uint32_t ui32Pipe, uint32_t ui32Event)
    //{
    //    int32_t i32Dev;
    //
    //    switch (ui32Event)
    //    {
    //        //
    //        // Handles a request to schedule a new request on the interrupt IN
    //        // pipe.
    //        //
    //        case USB_EVENT_SCHEDULER:
    //        {
    //            USBHCDPipeSchedule(ui32Pipe, 0, 1);
    //            break;
    //        }
    //        //
    //        // Called when new data is available on the interrupt IN pipe.
    //        //
    //        case USB_EVENT_RX_AVAILABLE:
    //        {
    //            //
    //            // Determine which device this notification is intended for.
    //            //
    //            for(i32Dev = 0; i32Dev < MAX_HID_DEVICES; i32Dev++)
    //            {
    //                //
    //                // Does this device own the pipe we have been passed?
    //                //
    //                if(g_psHIDDevice[i32Dev].ui32IntInPipe == ui32Pipe)
    //                {
    //                    //
    //                    // Yes - send the report data to the USB host HID device
    //                    // class driver.
    //                    //
    //                    g_psHIDDevice[i32Dev].pfnCallback(
    //                                    g_psHIDDevice[i32Dev].pvCBData,
    //                                    USB_EVENT_RX_AVAILABLE, ui32Pipe, 0);
    //                }
    //            }
    //
    //            break;
    //        }
    //    }
    //}
    
    //*****************************************************************************
    //
    //! This function is used to open an instance of the CDC driver.
    //!
    //! \param pDevice is a pointer to the device information structure.
    //!
    //! This function will attempt to open an instance of the CDC driver based on
    //! the information contained in the pDevice structure.  This call can fail if
    //! there are not sufficient resources to open the device.  The function will
    //! return a value that should be passed back into USBCDCClose() when the
    //! driver is no longer needed.
    //!
    //! \return The function will return a pointer to a CDC driver instance.
    //
    //*****************************************************************************
    static void *
    USBHCDCOpen(tUSBHostDevice *psDevice)
    {
        //printf("USBHCDCOpen: Start\n");
    
        int32_t i32Idx, i32Idz;
        tEndpointDescriptor *psEndpointDescriptor;
        tInterfaceDescriptor *psInterface;
    
        //
        // Don't allow the device to be opened without closing first.
        //
        if(g_USBHCDCDevice.psDevice)
        {
    		//printf("USBHCDCOpen: For Loop: i32Idx, %d\n", i32Idx);
    
            return(0);
        }
    
        //
        // Save the device pointer.
        //
        g_USBHCDCDevice.psDevice = psDevice;
    
        //
        //  Loop Through the first 3 Interfaces Searching for Endpoints
        //
        for(i32Idz = 0; i32Idz < 3; i32Idz++)
        {
    		//
    		// Get the interface descriptor.
    		//
    		psInterface = USBDescGetInterface(psDevice->psConfigDescriptor, i32Idz, 0);
    
    		//
    		// Loop through the endpoints of the device.
    		// bNumEndPoints returning 1, should be 3 - will set manually, as there is always 3...then it works!!!
    		//
    		for(i32Idx = 0; i32Idx < 3; i32Idx++)  //psInterface->bNumEndpoints; i32Idx++)
    		{
    			//
    			// Get the first endpoint descriptor.
    			//
    			psEndpointDescriptor =
    				USBDescGetInterfaceEndpoint(psInterface, i32Idx,
    											psDevice->ui32ConfigDescriptorSize);
    
    			//System_printf("USBHCDCOpen: psEndPointDecriptor: %d  bmAttribute: %d\n", psEndpointDescriptor, psEndpointDescriptor->bmAttributes);
    			//System_flush();
    
    			//
    			// If no more endpoints then break out.
    			//
    			if(psEndpointDescriptor == 0)
    			{
    				break;
    			}
    
    			//
    			// See if this is an Interrupt endpoint.
    			//
    			if((psEndpointDescriptor->bmAttributes & USB_EP_ATTR_TYPE_M) == USB_EP_ATTR_INT)
    			{
    				//
    				// Interrupt IN.
    				//
    				if(psEndpointDescriptor->bEndpointAddress & USB_EP_DESC_IN)
    				{
    					g_USBHCDCDevice.ui32IntInPipe =
    							USBHCDPipeAlloc(0, USBHCD_PIPE_INTR_IN,
    											psDevice, USBHCDCInterruptCallback);
    
    					USBHCDPipeConfig(g_USBHCDCDevice.ui32IntInPipe,
    								psEndpointDescriptor->wMaxPacketSize,
    								psEndpointDescriptor->bInterval,
    								(psEndpointDescriptor->bEndpointAddress &
    								 USB_EP_DESC_NUM_M));
    
    					//System_printf("USBHCDCOpen: Allocated and Configured Interrupt In Endpoint: Interface Index: %d  bEndPointAddress: %d  ui32BulkOutPipe: %d\n", i32Idz, psEndpointDescriptor->bEndpointAddress, g_USBHCDCDevice.ui32IntInPipe);
    					//System_flush();
    				}
    			}
    
    			//
    			// See if this is a bulk endpoint.
    			//
    			if((psEndpointDescriptor->bmAttributes & USB_EP_ATTR_TYPE_M) == USB_EP_ATTR_BULK)
    			{
    				//
    				// See if this is bulk IN or bulk OUT or Interrupt
    				//
    				//if((psEndpointDescriptor->bmAttributes & USB_EP_ATTR_INT) == USB_EP_ATTR_INT)
    				//{
    	//                //
    	//                // Allocate the USB Pipe for this Bulk IN Interrupt endpoint.
    	//                //
    	//                g_USBHCDCDevice.ui32BulkInPipe =
    	//                    USBHCDPipeAllocSize(0, USBHCD_PIPE_BULK_IN,
    	//                                        psDevice,
    	//                                        psEndpointDescriptor->wMaxPacketSize,
    	//                                        USBHCDCInterruptCallback);
    	//                //
    	//                // Configure the USB pipe as a Bulk IN endpoint.
    	//                //
    	//                USBHCDPipeConfig(g_USBHCDCDevice.ui32BulkInPipe,
    	//                                 psEndpointDescriptor->wMaxPacketSize,
    	//                                 1,
    	//                                 (psEndpointDescriptor->bEndpointAddress &
    	//                                  USB_EP_DESC_NUM_M));
    	//
    	//				System_printf("USBHCDCOpen: Allocated and Configured Interrupt EndPoint**: Interface Index: %d  bEndPointAddress: %d  ui32BulkOutPipe: %d\n", i32Idz, psEndpointDescriptor->bEndpointAddress, g_USBHCDCDevice.ui32BulkOutPipe);
    	//				System_flush();
        //
    	//			}
    				if(psEndpointDescriptor->bEndpointAddress & USB_EP_DESC_IN)
    				{
    					//
    					// Allocate the USB Pipe for this Bulk IN endpoint.
    					//
    					g_USBHCDCDevice.ui32BulkInPipe =
    						USBHCDPipeAllocSize(0, USBHCD_PIPE_BULK_IN,
    											psDevice,
    											psEndpointDescriptor->wMaxPacketSize,
    											USBHCDCINCallback);
    					//
    					// Configure the USB pipe as a Bulk IN endpoint.
    					//
    					USBHCDPipeConfig(g_USBHCDCDevice.ui32BulkInPipe,
    									 psEndpointDescriptor->wMaxPacketSize,
    									 64,
    									 (psEndpointDescriptor->bEndpointAddress &
    									  USB_EP_DESC_NUM_M));
    
    					//System_printf("USBHCDCOpen: Allocated and Configured Bulk In EndPoint: Interface Index: %d  bEndPointAddress: %d  ui32BulkOutPipe: %d\n", i32Idz, psEndpointDescriptor->bEndpointAddress, g_USBHCDCDevice.ui32BulkOutPipe);
    					//System_flush();
    
    				}
    				else
    				{
    					//
    					// Allocate the USB Pipe for this Bulk OUT endpoint.
    					//
    					g_USBHCDCDevice.ui32BulkOutPipe =
    						USBHCDPipeAllocSize(0, USBHCD_PIPE_BULK_OUT,
    											psDevice,
    											psEndpointDescriptor->wMaxPacketSize,
    											0);
    					//
    					// Configure the USB pipe as a Bulk OUT endpoint.
    					//
    					USBHCDPipeConfig(g_USBHCDCDevice.ui32BulkOutPipe,
    									 psEndpointDescriptor->wMaxPacketSize,
    									 0,
    									 (psEndpointDescriptor->bEndpointAddress &
    									  USB_EP_DESC_NUM_M));
    
    					//System_printf("USBHCDCOpen: Allocated and Configured Bulk Out EndPoint: Interface Index: %d  bEndPointAddress: %d  ui32BulkOutPipe: %d\n", i32Idz, psEndpointDescriptor->bEndpointAddress, g_USBHCDCDevice.ui32BulkOutPipe);
    					//System_flush();
    				}
    			}
    		}
        }
    
    
        //
        // If there is a callback function call it to inform the application that
        // the device has been enumerated.
        //
        // To be used with the RTOS callback handler example.
        //
    //    if(g_USBCDCDevice.pfnCallback != 0)
    //    {
    //        g_psHIDDevice[i32Dev].pfnCallback(
    //                            g_psHIDDevice[i32Dev].pvCBData,
    //                            USB_EVENT_CONNECTED,
    //                            (uint32_t)&g_psHIDDevice[i32Dev], 0);
    //    }
    
        //
        // If the callback exists, call it with an Open event.
        //
        if(g_USBHCDCDevice.pfnCallback != 0)
        {
           // printf("USBHCDCOpen: Callback Exists: Calling\n");
           // System_flush();
    
            g_USBHCDCDevice.pfnCallback(&g_USBHCDCDevice,
                                        CDC_EVENT_OPEN, 0, 0);
        }
    
        //
        // Return the only instance of this device.
        //
        return(&g_USBHCDCDevice);
    }
    
    //*****************************************************************************
    //
    //! This function is used to release an instance of the CDC driver.
    //!
    //! \param pvInstance is an instance pointer that needs to be released.
    //!
    //! This function will free up any resources in use by the CDC driver instance
    //! that is passed in.  The \e pvInstance pointer should be a valid value that
    //! was returned from a call to USBCDCOpen().
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    USBHCDCClose(void *pvInstance)
    {
        //
        // Do nothing if there is not a driver open.
        //
        if(g_USBHCDCDevice.psDevice == 0)
        {
            return;
        }
    
        //
        // Reset the device pointer.
        //
        g_USBHCDCDevice.psDevice = 0;
    
        //
        // Free the Bulk IN Interrupt pipe.
        //
        if(g_USBHCDCDevice.ui32IntInPipe != 0)
        {
            USBHCDPipeFree(g_USBHCDCDevice.ui32IntInPipe);
        }
    
        //
        // Free the Bulk IN pipe.
        //
        if(g_USBHCDCDevice.ui32BulkInPipe != 0)
        {
            USBHCDPipeFree(g_USBHCDCDevice.ui32BulkInPipe);
        }
    
        //
        // Free the Bulk OUT pipe.
        //
        if(g_USBHCDCDevice.ui32BulkOutPipe != 0)
        {
            USBHCDPipeFree(g_USBHCDCDevice.ui32BulkOutPipe);
        }
    
        //
        // If the callback exists then call it.
        //
        if(g_USBHCDCDevice.pfnCallback != 0)
        {
            //printf("USBHCDCClose: Callback Exists: Calling\n");
    
            g_USBHCDCDevice.pfnCallback(&g_USBHCDCDevice,
                                        CDC_EVENT_CLOSE, 0, 0);
        }
    }
    
    //*****************************************************************************
    //
    //! This function checks if a drive is ready to be accessed.
    //!
    //! \param ulInstance is the device instance to use for this read.
    //!
    //! This function checks if the current device is ready to be accessed.
    //! It uses the \e ulInstance parameter to determine which device to check and
    //! will return zero when the device is ready.  Any non-zero return code
    //! indicates that the device was not ready.
    //!
    //! \return This function will return zero if the device is ready and it will
    //! return a other value if the device is not ready or if an error occurred.
    //
    //*****************************************************************************
    unsigned char TestPipeOut[] = "AT\n\r";
    int32_t
    USBHCDCReady(tUSBHCDCInstance *psCDCInstance)
    {
    
    	//System_printf("USBHCDCReady: Start\n");
    	//System_flush();
    
        struct tLineCoding	lc;
        struct tLineStatus	ls;
    
        //
        // If there is no device present then return an error.
        //
        if(psCDCInstance->psDevice == 0)
        {
        	//System_printf("USBHCDCReady: No Device Present");
        	//System_flush();
    
            return(-1);
        }
    
        //
        //  Open an instance of the CDC driver.
        //
        //USBHCDCOpen(psCDCInstance->psDevice);
       // USBHCDCOpen(psCDCInstance->psDevice);
        //
        // Set Control Line
        //
        ACMSetControlLineState(psCDCInstance,2);  //ACMSetControlLineState(g_USBHCDCDevice.pDevice, g_USBHCDCDevice.pDevice->ulAddress,1);
    
        //
        // Set Control Line
        //
        ACMSetControlLineState(psCDCInstance, 0); //    ACMSetControlLineState(g_USBHCDCDevice.pDevice, g_USBHCDCDevice.pDevice->ulAddress,3);
    
        //
        // Get Line Status - we will just set for now, as we know what is required
        //
        //memset(&lc,0,sizeof(ls));
        //ACMGetLineStatus(g_USBHCDCDevice.psDevice, &ls);
    
        //
        // Set line coding
        //
        lc.dwDTERate = 19200;
        lc.bCharFormat = 0;
        lc.bParityType = 0;
        lc.bDataBits = 8;
    
        //
        // Get line coding
        //
        //memset(&lc,0,sizeof(lc));  // this reset everything in lc to 0
        //ACMGetLineCoding(g_USBHCDCDevice.psDevice, &lc);  - We will just set for now, as we know what is required.
    
        ACMSetLineCoding(psCDCInstance); //, &lc);
    
        //USBHCDPipeWrite(pCDCDevice->ulBulkOutPipe,
        //                          (unsigned char*)TestPipeOut, sizeof(TestPipeOut)-1);
    
        //
        // Success.
        //
        return(0);
    }
    
    //*****************************************************************************
    //
    //! This function is used to set control line
    //!
    //! \param State is a line state
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    //void USBHCDCSetControlLine(int State)
    //{
    //        //
    //        // Set Control Line
    //        //
    //        ACMSetControlLineState(g_USBHCDCDevice, State);
    //}
    
    //*****************************************************************************
    //
    //! This function is used to set appropriate line coding
    //!
    //! \param None
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    //void USBHCDCSetLineCoding(void)
    //{
    //    struct tLineCoding	lc;
    //    //
    //    // Set line coding
    //    // (need to set to what the device responds with in the USBHCDCSetLineCoding
    //    // For now we will set this manually to what the mini controller responds with
    //    // But this should be changed in the future to ensure support for other devices
    //    // that may have different requirements.
    //    //
    //    lc.dwDTERate = 19200;  // This is the baud rate
    //    lc.bCharFormat = 0; // 0 is equal to 1 stop bit
    //    lc.bParityType = 0;  // 0 is equal to parity of none
    //    lc.bDataBits = 8; // Number of data bits
    //    ACMSetLineCoding(g_USBHCDCDevice, &lc);
    //}
    
    //*****************************************************************************
    //
    //! This function sends out data to connected CDC device.
    //!
    //! \param ulInstance is the device instance
    //! \param pucData is the pointer to data buffer to be sent out
    //! \param ulSize is the size of data to be sent out in bytes
    //!
    //! \return This function will return number of data in bytes scheduled to
    //! 		sent out.
    //
    //*****************************************************************************
    int32_t
    USBHCDCWrite(tUSBHCDCInstance *psCDCInstance, unsigned char *pucData, int32_t ulSize)
    {
    	//System_printf("USBHCDCWrite: Start\n");
    	//System_flush();
    
        //
        // If there is no device present then return an error.
        //
        if(psCDCInstance->psDevice == 0)
        {
            return(0);
        }
    
        //
        // Send data through OUT pipe  (MAY NEED TO LOOK AT psCDCInstance)
        //
        return (USBHCDPipeWrite(psCDCInstance->ui32BulkOutPipe, pucData, ulSize));
        //return (USBHCDPipeWrite(2, pucData, ulSize));
    
    }
    
    
    //*****************************************************************************
    //
    //! This function is used to send chars to Bulk Out Pipe
    //!
    //! \param *pcData is pointer to data
    //! \param Size is number of bytes
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    void USBHCDCSendChars(unsigned char *pucData, uint32_t ulSize)
    {
        USBHCDPipeWrite(g_USBHCDCDevice.ui32BulkOutPipe, pucData, ulSize);
    }
    
    
    //*****************************************************************************
    //
    //! This function is used to send chars to Bulk Out Pipe
    //!
    //! \param *pcData is pointer to data
    //! \param Size is number of bytes
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    void USBHCDCSendString(unsigned char *pucData)
    {
        int Size = 0, Page = 0;
    
        while(pucData[Size] != 0)
        {
            Size ++;
            if(Size % 64)
            {
                //
                // Send out full pipe
                //
                USBHCDPipeWrite(g_USBHCDCDevice.ui32BulkOutPipe,&pucData[Page], Size);
    
                //
                // Increment Page
                //
                Page++;
            }
        }
    
        //
        // If anything left, send out
        //
        if(Size)
        	USBHCDCWrite(0, pucData, Size);
    
        	//USBHCDPipeWrite(g_USBHCDCDevice.ulBulkOutPipe,&pucData[Page], Size);
    }
    
    //*****************************************************************************
    //
    //! This function is used to get line status
    //!
    //! \param *pcData is pointer to data
    //! \param Size is number of bytes
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    //void USBHCDCGetLineStatus(int *LineState, int *CallState)
    //{
    //    struct tLineStatus	ls;
    //    //
    //    // Get Line Status
    //    //
    //    memset(&ls,0,sizeof(ls));
    //    ACMGetLineStatus(g_USBHCDCDevice, &ls);
    //    *LineState = ls.dwLineState;
    //    *CallState = ls.dwCallState;
    //}
    
    //*****************************************************************************
    //
    //! This function should be called before any devices are present to enable
    //! the CDC class driver.
    //!
    //! \param ulDrive is the drive number to open.
    //! \param pfnCallback is the driver callback for any CDC events.
    //!
    //! This function is called to open an instance of a CDC device.  It
    //! should be called before any devices are connected to allow for proper
    //! notification of drive connection and disconnection.  The \e ulDrive
    //! parameter is a zero based index of the drives present in the system.
    //! There are a constant number of drives, and this number should only
    //! be greater than 0 if there is a USB hub present in the system.  The
    //! application should also provide the \e pfnCallback to be notified of mass
    //! storage related events like device enumeration and device removal.
    //!
    //! \return This function will return the driver instance to use for the other
    //! CDC functions.  If there is no driver available at the time of
    //! this call, this function will return zero.
    //
    //*****************************************************************************
    tUSBHCDCInstance *
    USBHCDCDriveOpen(uint32_t ui32Drive, tUSBHCDCCallback pfnCallback)
    {
    	//System_printf("USBCDriveOpen: Start\n");
    	//System_flush();
    
        //
        // Only the first drive is supported and only one callback is supported.
        //
        if((ui32Drive != 0) || (g_USBHCDCDevice.pfnCallback))
        {
            return(0);
        }
    
        //
        // Save the callback.
        //
        g_USBHCDCDevice.pfnCallback = pfnCallback;
    
        //
        // Return the requested device instance.
        //
        return(&g_USBHCDCDevice);
    }
    
    
    //*****************************************************************************
    //
    //! This function sets ACM baud rate
    //!
    //! \param ulAddress is the device address on the USB bus.
    //! \param *dataptr is pointer to line coding structure
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    int ACMSetLineCoding(tUSBHCDCInstance *psCDCInstance)  //, struct tLineCoding *dataptr)
    {
    	//System_printf("ACMSetLineCoding: Start\n");
    	//System_flush();
    
        tUSBRequest SetupPacket;
    
        //
        // This is a Class specific interface OUT request.
        //
        SetupPacket.bmRequestType = bmREQ_CDCOUT;
    
        //
        // Request a set baud rate
        //
        SetupPacket.bRequest = CDC_SET_LINE_CODING;
        SetupPacket.wValue = 0;
    
        //
        // Indicate the index
        //
        SetupPacket.wIndex = 0;
    
        //
        // Zero bytes request
        //
        SetupPacket.wLength = 7;  //sizeof(struct tLineCoding);
    
    
        // This is 19200, 8, N, 1
    	unsigned char byteLC[] = { 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x08 };
    
    	unsigned char *byteLCPtr;
    	byteLCPtr = byteLC;
    
        //
        // Put the setup packet in the buffer and send the command.
        //
        if(USBHCDControlTransfer(0, &SetupPacket, psCDCInstance->psDevice, byteLCPtr, 7, MAX_PACKET_SIZE_EP0))
        {
    		return 1;
        }
    
        return 0;
    }
    
    //*****************************************************************************
    //
    //! This function gets ACM line coding
    //!
    //! \param ulAddress is the device address on the USB bus.
    //! \param *dataptr is pointer to line coding structure
    //!
    //! \return None.
    //
    //*****************************************************************************
    int ACMGetLineCoding(tUSBHCDCInstance *psCDCInstance)   //, struct tLineCoding *dataptr)
    {
    	//System_printf("ACMGetLineCoding: Start\n");
    	//System_flush();
    
        tUSBRequest SetupPacket;
    
        //
        // This is a Class specific interface OUT request.
        //
        SetupPacket.bmRequestType = bmREQ_CDCIN;
    
        //
        // Request a set baud rate
        //
        SetupPacket.bRequest = CDC_GET_LINE_CODING;
        SetupPacket.wValue = 0;
    
        //
        // Indicate the index
        //
        SetupPacket.wIndex = 0;
    
        //
        // Zero bytes request
        //
        SetupPacket.wLength = 7; // sizeof(struct tLineCoding);
    
        // This is 19200, 8, N, 1
    	unsigned char byteLC[] = { 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x08 };
    
    	unsigned char *byteLCPtr;
    	byteLCPtr = byteLC;
    
        //
        // Put the setup packet in the buffer and send the command.
        //
        if(USBHCDControlTransfer(0, &SetupPacket, psCDCInstance->psDevice, byteLCPtr, 7, MAX_PACKET_SIZE_EP0))
        {
    		return 1;
        }
    
        return 0;
    }
    
    //*****************************************************************************
    //
    //! This function sets ACM Control Line
    //!
    //! \param ulAddress is the device address on the USB bus.
    //! \param State is the State of Control Line
    //!
    //! \return None.
    //
    //*****************************************************************************
    int ACMSetControlLineState(tUSBHCDCInstance *psCDCInstance,  int State)
    {
    	//System_printf("ACMSetControlLineState: Start\n");
    	//System_flush();
    
    	tUSBRequest SetupPacket;
    
        //
        // This is a Class specific interface OUT request.
        //
        SetupPacket.bmRequestType = bmREQ_CDCOUT;  // 0 - host to
    
        //
        // Request a set baud rate
        //
        SetupPacket.bRequest = CDC_SET_CONTROL_LINE_STATE;
        SetupPacket.wValue = State;
    
        //
        // Indicate the index
        //
        SetupPacket.wIndex = State; // 2; //This depends on wValue - should be the same the wValue
    
        //
        // Zero bytes request
        //
        SetupPacket.wLength = 0;
    
        //
        // Put the setup packet in the buffer and send the command.
        //
        if(USBHCDControlTransfer(0, &SetupPacket, psCDCInstance->psDevice, 0, 0, MAX_PACKET_SIZE_EP0))
        {
    		return 1;
        }
    
        return 0;
    }
    
    //*****************************************************************************
    //
    //! This function gets ACM Control Line
    //!
    //! \param ulAddress is the device address on the USB bus.
    //! \param State is the State of Control Line
    //!
    //!
    //! \return None.
    //
    //*****************************************************************************
    int ACMGetLineStatus(tUSBHCDCInstance *psCDCInstance)  //, struct tLineStatus *dataptr)
    {
    	//System_printf("ACMGetLineState: Start\n");
    	//System_flush();
    
        tUSBRequest SetupPacket;
    
        //
        // This is a Class specific interface IN request.
        //
        SetupPacket.bmRequestType = bmREQ_CDCIN;
    
        //
        // Request a set baud rate
        //
        SetupPacket.bRequest = CDC_GET_LINE_PARMS;
        SetupPacket.wValue = 0;
    
        //
        // Indicate the index
        //
        SetupPacket.wIndex = 0;
    
        //
        // Size of Structure
        //
        SetupPacket.wLength = 7; //sizeof(struct tLineStatus);
    
        //
        // Put the setup packet in the buffer and send the command.
        //
        if(USBHCDControlTransfer(0, &SetupPacket, psCDCInstance->psDevice, 0, 0, MAX_PACKET_SIZE_EP0))
        {
    		return 1;
        }
    
        return 0;
    }
    
    //! \param ui32Index is the controller index to use for this transfer.
    //! \param psSetupPacket is the setup request to be sent.
    //! \param psDevice is the device instance pointer for this request.
    //! \param pui8Data is the data to send for OUT requests or the receive buffer
    //! for IN requests.
    //! \param ui32Size is the size of the buffer in pui8Data.
    //! \param ui32MaxPacketSize is the maximum packet size for the device for this
    //! request.
    //    ulRet = USBHCDControlTransfer(0, &sReq, pFTDIDevice->pDevice, ucData, 0, MAX_PACKET_SIZE_EP0);
    
    
    ////*****************************************************************************
    ////
    ////! This function gets Comm Feature
    ////!
    ////! \param ulAddress is the device address on the USB bus.
    ////! \param State is the State of Control Line
    ////!
    ////!
    ////! \return None.
    ////
    ////*****************************************************************************
    //int ACMGetCommFeature(tUSBHostDevice *psDevice, struct tCommFeature *dataptr)
    //{
    //    tUSBRequest SetupPacket;
    //
    //    //
    //    // This is a Class specific interface IN request.
    //    //
    //    SetupPacket.bmRequestType = bmREQ_CDCIN;
    //
    //    //
    //    // Request a set baud rate
    //    //
    //    SetupPacket.bRequest = CDC_GET_COMM_FEATURE;
    //    SetupPacket.wValue = 1;
    //
    //    //
    //    // Indicate the index
    //    //
    //    SetupPacket.wIndex = 0;
    //
    //    //
    //    // Size of Structure
    //    //
    //    SetupPacket.wLength = sizeof(struct tLineStatus);;
    //
    //    //
    //    // Put the setup packet in the buffer and send the command.
    //    //
    //    if(USBHCDControlTransfer(0,
    //                             &SetupPacket,
    //                             psDevice,
    //                             (unsigned char *)dataptr,
    //                             sizeof(struct tLineStatus),
    //                             MAX_PACKET_SIZE_EP0))
    //    {
    //		return 1;
    //    }
    //
    //    return 0;
    //}
    
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    
     0131.usbhcdc.h  6644.usbhostenum.c

    You will need to add the following to usbhost.h

    extern const tUSBHostClassDriver g_sUSBHostCDCClassDriver;

    Here are some of the important points for the program code. I suggest starting with one of the examples provided with Tivaware or TI-RTOS for a similar device. And then altering it to your needs.

    mainprogram.c
    
    // USB Headers
    #include "usblib/usblib.h"
    #include "usblib/host/usbhost.h"
    #include "usblib/host/usbhcdc.h"
    
    // A list of available Host Class Drivers, we only add CDC driver
    static tUSBHostClassDriver const * const usbHCDDriverList[] = {
        &g_sUSBHostCDCClassDriver,
        &USBCDCH_eventDriver
    };
    
    
    Add this to where you initialise the you USB CDC
    
    void USBCDCH_init(Void)
    {
    :
    :
        // Initialize the USB stack for host mode. 
        USBStackModeSet(0, eUSBModeForceHost, NULL);
    
        // Register host class drivers 
        USBHCDRegisterDrivers(0, usbHCDDriverList, numHostClassDrivers);
    
        // Open an instance of the CDC host driver 
        CDCInstance = USBHCDCDriveOpen(0, CDCCallback);
    :
    :
    }
    
    
    Add this to your main program loop
    
        // Call the USB stack to keep it running.
        USBHCDMain();
    
    
    Use something like this to send data out the bulk output 
    
    void singlePacket(tUSBHCDCInstance *psCDCInstance)
    {
    
    :
    :
        int byteCount = 0;
        byteCount = USBHCDCWrite(psCDCInstance, packetPtr, totalSize);
    :
    :
    }

    Best of luck, this should save you at least a weeks work ;-)

    Glenn.

  • Thanks Glenn!  I'll give that a try.

  • Dear all,

    My query is if I need to connect pendrive with tiva C123G launchpad kit and use the tiva C as a host and dump my data in pendrive what should I do..? where to start?

    should I go for MSD device class or CDC class.?

    Please suggest.

  • MSD (Mass Storage Device) Class would be the drivers you need to work with when it comes to flash memory. Check out usbhmsc.h and usbhmsc.c in the host folder of TivaWear usblib. I have not done this my self, but you may also need to look into Fatfs library...but it may only be required if you need to format.

    Glenn.
  • I have added the source code for the drivers, along with instructions on Github.

    My Github account is here - https://github.com/remixed123

    Look for the tiva-c_usb_host_cdc_driver repository. There is also code available for the CC3200 should you be interested in developing for that platform.

    Glenn.

  • /Dear all,/
    
    /here I have written some code for USB detection and writing data in pendrive,
    /please see to it and let me know errors.../
    /I have attached screenshot for errors/
    
    
    
    
    
    
    
    /**************************DOCUMENTATION*******************************/
    /**********************USB CODE*****************************************/
    
    /****DATE:17/12/2014********/
    
     /* main.c
     */
    	
    	//TM4C123GH6PMI USB Host functionality
    	// Basic configuration as a host- mass storage programming example
    
    	//The following code shows the basic setup code needed for any application that is using the USB library in host mode. The g_pui8HCDPool array which is passed to the USBHCDInit( ) is used as a heap memory for by the USB library and thus should not be used by the application. In this example, the g_ppsHostClassDrivers array holds the MSC (mass storage class) drivers. The macros provided in the pin_map.h file included with DriverLib can be used to indicate which pin and peripheral to use for a given part. The USBHCDRegisterDrivers( ) call passes in the static array of supported USB host class drivers that are supported by the application. Typically, the reading or writing to a device is left to a file system layer or through direct read and write calls.
    
    #include "inc/tm4c123gh6pm.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include "driverlib/gpio.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/sysctl.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/rom.h"
    #include "driverlib/pin_map.h"
    
    
    
    //#include "packages/xdc/std.h"
    //#include "packages/xdc/runtime/System.h"
    
    #include "driverlib/usb.h"
    #include "inc/hw_usb.h"
    #include "usblib/host/usbhost.h"      //contains host mode function prototypes and data types
    #include "usblib/host/usbhmsc.h"    //contains Mass Storage Class definitions specific to hosts
    #include "usblib/usblib.h"
    #include "usblib/usbmsc.h"
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //********************************************************************************************************************************
    
    	#define HCD_MEMORY_SIZE 128    //the size of the host controller’s memory size in bytes
    	unsigned char g_pui8HCDPool [HCD_MEMORY_SIZE];  //the memory pool to provide to the host controller driver
    
    	static tUSBHostClassDriver const  * const g_ppsHostClassDrivers[] =
    						{
    								&g_sUSBHostMSCClassDriver
    						};
    	// the global that holds all of the host drivers in use in the application
    
    	static const unsigned long g_ui32NumHostClassDrivers =	sizeof ( g_ppsHostClassDrivers ) / sizeof ( tUSBHostClassDriver * );
    	//this global holds the number of class drivers in the g_ppsHostClassDrivers list
    
    // USB MSD control
    #define MSD_NOT_CONNECTED 0
    #define MSD_INIT 1
    #define MSD_CONNECTED 2
    
    uint32_t iMSDState= MSD_NOT_CONNECTED; 				//initial value 0
    
    //************************************************************************************************************
    
    // MSCCallBack
    
    //*************************************************************************************************************
    void MSCCallBack (uint32_t ui32Event)
    	{
    	switch (ui32Event)
    		{
    			// new pen drive detected
    		case USB_EVENT_CONNECTED:
    			{
    				iMSDState= MSD_INIT;
    				break;
    			}
    
    			//pen drive has been unplugged
    
    		case USB_EVENT_DISCONNECTED:
    			{
    				iMSDState= MSD_NOT_CONNECTED;
    				break;
    			}
    
    		}
    	}
    
    //*************************************************************************************************************
    
    //Application Start
    
    //**************************************************************************************************************
    
    	void main (void)
    	{
    
    	//	const tUSBHostClassDriver * const * g_ppsUSBHostClassDrivers;
    	//	uint8_t *ptr;
    
    
    	// Set the clocking to run from the PLL at 50 MHz
    		SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    		SysCtlUSBPLLEnable();
    	// enable clocking
    		SysCtlPeripheralEnable (SYSCTL_PERIPH_USB0);
    	//Initialize the USB stack for host mode
    		USBStackModeSet(0,eUSBModeHost,0);
    
    
    	//Enable the GPIO peripherals used by the USB pins
    		SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOB);
    
    	//enable PB0 and PB1 as VBUS and ID pins
    		GPIOPinTypeUSBAnalog (GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);         // PB0- VBUS; PB1- ID
    
    
    		SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOL);
    	// Enable the D+/ D- as USB pins
    		GPIOPinTypeUSBAnalog (GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);         // PL6- D+, PL7- D-
    
    		SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOG);
    
    	// configure USBEPEN as a USB pin
    		GPIOPinConfigure (GPIO_PG4_USB0EPEN);
    		GPIOPinTypeUSBDigital (GPIO_PORTG_BASE, GPIO_PIN_4);
    
    //*****************************************************************************************************************
    
    // LED initialization
    
    		volatile uint32_t ui32Loop;
    		    SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
    		    ui32Loop = SYSCTL_RCGC2_R;
    		    GPIO_PORTF_DIR_R = 0x08;
    		    GPIO_PORTF_DEN_R = 0x08;
    
    //*****************************************************************************************************************
    
    	//Register the host class drivers
    		USBHCDRegisterDrivers (0, g_ppsUSBHostClassDrivers, g_ui32NumHostClassDrivers);
    
    	// Initialize the power configuration. Set the power enable signal to be active high and does not enable the power fault.
    		USBHCDPowerConfigInit (0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER);
    
    
    	// call any open routines here for the application to be ready for a new mass storage device
    		tUSBHMSCInstance *g_psMSCInstance= USBHMSCDriveOpen (0, MSCCallBack);	 // open an instance of the mass storage class driver
    
    		USBHCDInit (0, g_pui8HCDPool, HCD_MEMORY_SIZE);  // initialize the host controller
    
    
    		// main loop of the application
    		while (1)
    			{
    			switch (iMSDState)
    				{
    				//This state is entered when the pen drive is first detected.
    				case MSD_INIT:
    					{
    					//initialize the newly connected pen drive
    					// wait for the drive to become ready- wait for the value to go to 0 before the host controller attempts to read or write from the device.
    							while ( USBHMSCDriveReady (g_psMSCInstance))
    								{
    								SysCtlDelay(g_ui32ClockRate / 100);          //delay given for the device to be ready
    								}
    						//move it to connected state
    						iMSDState= MSD_CONNECTED;
    						break;
    					}
    				case MSD_CONNECTED:
    					{
    					// glow an LED if the pen drive is detected.
    					GPIO_PORTF_DATA_R |= 0x08;
    					for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++);
    					GPIO_PORTF_DATA_R &= ~(0x08);
    					for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++);
    					break;
    					}
    				case MSD_NOT_CONNECTED:
    				default:
    					{
    					break;
    					}
    				}
    
    			USBHCDMain( );   // Periodic call for the Host Controller Drivers
    
    			}
    
    		}
    
    
    

  • Since your issue is now unrelated to the original post.....I am thinking you may get more people to look into your issue if you create a new thread.
  • Hi Glenn

    I have integrated your source code in usblib and make EVM as host cdc device, but it can send data only.

    I try to make it to receive data, but it's not work so far.

    I have some questions, if possible, may I have your suggestion?

    1. I connect a device to EVM and collect the log as below:

    --------------------

    USBHCDCOpen: psEndPointDecriptor: 536874141 bmAttribute: 3
    USBHCDPipeConfig: EP_PIPE_TYPE_IN
    USBHCDPipeConfig: EP_PIPE_TYPE_INTR
    Interrupt In Endpoint: Interface Index: 0 bEndPointAddress: 129 ui32IntInPipe: 4325376
    USBHCDCOpen: psEndPointDecriptor: 0 bmAttribute: 32
    USBHCDCOpen: psEndPointDecriptor: 536874157 bmAttribute: 2
    USBHCDCOpen: ui32BulkInPipe
    USBHCDPipeConfig: EP_PIPE_TYPE_IN
    USBHCDPipeConfig: EP_PIPE_TYPE_BULK
    Bulk In EndPoint: Interface Index: 1 bEndPointAddress: 130 ui32BulkInPipe: 2228225
    USBHCDCOpen: psEndPointDecriptor: 536874164 bmAttribute: 2
    USBHCDPipeConfig: EP_PIPE_TYPE_OUT
    Bulk Out EndPoint: Interface Index: 1 bEndPointAddress: 1 ui32BulkOutPipe: 2162688
    USBHCDCOpen: psEndPointDecriptor: 0 bmAttribute: 32
    USBHCDCOpen: psEndPointDecriptor: 0 bmAttribute: 32
    USBHCDCOpen: Callback Exists: Calling
    CDC_EVENT_OPEN
    USB_EVENT_UNKNOWN_CONNECTED

    -------------------

    From log, that should be setup interrupt/ bulk in/bulk out in endpoint successfully, right?

    In other word, does it mean that enumeration is done?

    2. When device send data to EVM, I always get USB_EVENT_RX_AVAILABLE event. but I can't get data.

    In my understanding, EVM has gotten the RX data receive notification, that means there is data in buffer.

    I use the function to get the data

    "USBHCDPipeRead(psCDCInstance->ui32BulkInPipe, pucData, ulSize)" or 
    "USBHCDPipeReadNonBlocking(g_USBHCDCDevice.ui32BulkInPipe, pucData, ulSize)" 

     ,parse SchedulePipeInBuffer in USBHCDCINCallback when interrupt occurred. but I always get the zero.

    thanks

    Gavin

  • Hi Gavin,

    I assume you are using the open source USB CDC driver I have made available here - github.com/.../tiva-c_usb_host_cdc_driver

    One thing as you will not from the detailed readme, is that I point out that CDC devices are not all the same in the way they implement Intefaces and Ports, the order of these could be different. Hence you need to first have a clear understanding of what your CDC device looks like by using USBlyzer and then you need to code to match this. This will involve stepping through the driver and understanding when you need to perform a certain call at the appropriate enumeration.

    It was a while since I developed this driver, so my memory is not the best, hence I am unlikely to be able to offer any additional advice.

    If you do get receiving working, it would be nice to send a Git Push to my repository so others can benefit from our work.

    Glenn.

  • Hi, Gavin,

    I am really interested in whether you get it working also. I am trying to accomplish the same thing.

    --Dave
  • Hi Dave

    Sorry, I still can't get it work. So I can't share any useful information for you.

    You can reference Glenn's previous porting driver, maybe you can get more ideas.

    thanks
    Gavin