This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB CDC Host

Hi !

I have to implement an USB CDC Host driver for STM32F4 controller.
Has anyone an idea/example how to do that. I only found examples for CDC Device.

Thanks

Marc

  • Here is a brief summary of ST Micro's host stack, which is common to STM32F105/107,F2xx,F4xx

    STM32F105/7 and STM32F2xx USB on-the-go Host and device library (UM1021) v2.0.0
    www.st.com/.../stm32_f105-07_f2xx_usb-host-device_lib.zip

    To implement CDC, modify usbh_msc_core.c
    Your application over CDC is written in usbh_usr.c, USBH_USR_Application()

    // Summary of ST Micro host stack
    //    STM32_F105-07_F2xx_USB-Host-Device_Lib_V2.0.0
    //    STM32F4-Discovery_FW_V1.1.0
    //     -- STM32_USB_Device/Host/OTG_Library are identical with above library
    
    //
    // Host stack Framework
    //
    
    #include "usbh_core.h"
    #include "usbh_usr.h"
    
    USB_OTG_CORE_HANDLE           USB_OTG_Core;
    USBH_HOST                     USB_Host;
    extern USBH_Class_cb_TypeDef  USBH_MSC_cb;
    extern USBH_Usr_cb_TypeDef    USR_Callbacks;
    
    int main(void)
    {
      /* Init Host Library */
      USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks);
    
      while (1)
      {
        /* Host Task handler */
        USBH_Process(&USB_OTG_Core, &USB_Host);
      }
    }
    
    //
    // Class driver   - refer to usbh_msc_core.c for typical implementation
    //
    
    
    #include "usbh_core.h"
    // callbacks from USBH_Process() in main loop USBH_Class_cb_TypeDef USBH_MSC_cb = { USBH_ClassDrv_InterfaceInit, USBH_ClassDrv_InterfaceDeInit, USBH_ClassDrv_ClassRequest, USBH_ClassDrv_Handle, };
    static USBH_Status USBH_ClassDrv_InterfaceInit( USB_OTG_CORE_HANDLE *pdev, void *phost ) { USBH_HOST *pphost = phost;
    // check interface/endpoint descriptors, if the target interface is supported or not pphost->device_prop.Itf_Desc[0].bInterfaceClass pphost->device_prop.Itf_Desc[0].bInterfaceProtocol pphost->device_prop.Ep_Desc[0][0].bEndpointAddress
    // open pipes using USBH_Alloc_Channel() / USBH_Open_Channel()
    if ( not_supported ) pphost->usr_cb->USBH_USR_DeviceNotSupported();
    return USBH_OK; }
    static void USBH_ClassDrv_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev, void *phost) { // close pipes USB_OTG_HC_Halt() / USBH_Free_Channel() }
    static USBH_Status USBH_ClassDrv_ClassRequest(USB_OTG_CORE_HANDLE *pdev, void *phost) { // initialization of USBH_ClassDrv_Handle() return USBH_OK; }
    static USBH_Status USBH_ClassDrv_Handle(USB_OTG_CORE_HANDLE *pdev, void *phost) { // state machine to run this class // first, put class specific requests, if required // run class-specific protocol over USB while in idle, call ((USBH_HOST *)phost)->usr_cb->USBH_USR_Application()
    return USBH_OK; }
    //
    // Callbacks from host stack     -- usbh_usr.c
    //
    
    #include "usbh_usr.h"
    
    USBH_Usr_cb_TypeDef USR_Callbacks =
    {
      USBH_USR_Init,
      USBH_USR_DeInit,
      USBH_USR_DeviceAttached,
      USBH_USR_ResetDevice,
      USBH_USR_DeviceDisconnected,
      USBH_USR_OverCurrentDetected,
      USBH_USR_DeviceSpeedDetected,
      USBH_USR_Device_DescAvailable,
      USBH_USR_DeviceAddressAssigned,
      USBH_USR_Configuration_DescAvailable,
      USBH_USR_Manufacturer_String,
      USBH_USR_Product_String,
      USBH_USR_SerialNum_String,
      USBH_USR_EnumerationDone,
      USBH_USR_UserInput,
      USBH_USR_Application,
      USBH_USR_DeviceNotSupported,
      USBH_USR_UnrecoveredError
    };
    
    Most of callbacks are copied as is from existing usbh_usr.c
    
    int USBH_USR_Application(void)
    {
      //
      // application-specific state machine
      // called from USBH_Process() -> USBH_ClassDrv_Handle()
      //
    
      return 0;
    }
    
    // control transfer
    
    
    // fill setup packet phost->Control.setup.b.bmRequestType phost->Control.setup.b.bRequest phost->Control.setup.b.wValue.w phost->Control.setup.b.wIndex.w phost->Control.setup.b.wLength.w
    Call USBH_CtlReq() repeatedly while it returns USBH_BUSY when finishes, it returns USBH_OK / USBH_FAIL / USBH_NOT_SUPPORTED (got STALL from device)
    // bulk transfer OUT 1) call USBH_BulkSendData() 2) poll HCD_GetURB_State() while it returns USBH_BUSY when finishes, HCD_GetURB_State() returns URB_DONE IN 1) call USBH_BulkReceiveData() 2) same as above
    // interrupt transfer OUT USBH_InterruptSendData() IN USBH_InterruptReceiveData() same as above bulk transfer

    Tsuneo

  • Hi Tsuneo !

    Thank you very much for reply. I will test your advice, but unfortunately I am not very firm in USB Classes. If you have (written) such a file/stack please let me know.

    Marc

  • In most cases, you don't need to realize CDC spec in depth.
    I believe your target device doesn't require full-spec CDC host.

    To make it sure, examine your target CDC device on a PC using a terminal application.
    Does your target device need any of these serial port features?
    1) Baudrate, data bits and parity setting
    2) DSR/DTR, CTS, RI, DCD handshake
    3) Detection of parity, overrun and frame errors
    4) Break signaling

    If none of them is required, you may simplify the host code so much.
    Just take care of bulk IN and OUT endpoints.

    Tsuneo

  • When I attach the CDC device to my CDC host and I put a breakpoint at the following function the value of
    pphost->device_prop.Itf_Desc[0].bInterfaceClass is 0xFF but it should be 0x02 for CDC_CLASS

    static USBH_Status USBH_ClassDrv_InterfaceInit( USB_OTG_CORE_HANDLE *pdev, void *phost )
    {
      USBH_HOST *pphost = phost;
    
    
      // check interface/endpoint descriptors, if the target interface is supported or not
        pphost->device_prop.Itf_Desc[0].bInterfaceClass
        pphost->device_prop.Itf_Desc[0].bInterfaceProtocol
        pphost->device_prop.Ep_Desc[0][0].bEndpointAddress
    
    

    When I attach the CDC device to PC I get two virtual COM-Ports which I can use with Terminal.

  • > When I attach the CDC device to PC I get two virtual COM-Ports which I can use with Terminal.

    For confirmation, did you read out the descriptors of the target device on a PC?
    Virtual COM ports may derive from a vendor specific device using a custom PC driver. For example, FTDI and SiLabs apply vendor specific devices for their USB-UART chips.

    UVCView is a handy utility to see USB descriptors on PC.
    (Maybe, USBView can't display such a complicated descriptor set by its bug)
    I attached UVCView to this post.
    " href= "http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=11800"> www.microsoft.com/.../details.aspx

    Please post the descriptors of the target device, to make our discussion forward ;-)

    Tsuneo

  • The output of UVCView shows:

    [Port3]  :  USB-Verbundgerät
    
              ---===>Device Information<===---
    English product name: "Motorola Tetra Radio"
    
    ConnectionStatus:
    Current Config Value:              0x01  -> Device Bus Speed: High
    Device Address:                    0x01
    Open Pipes:                           4
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x01  -> Direction: OUT - EndpointID: 1
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x82  -> Direction: IN - EndpointID: 2
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Device Descriptor<===
    bLength:                           0x12
    bDescriptorType:                   0x01
    bcdUSB:                          0x0200
    bDeviceClass:                      0x00  -> This is an Interface Class Defined Device
    bDeviceSubClass:                   0x00
    bDeviceProtocol:                   0x00
    bMaxPacketSize0:                   0x40 = (64) Bytes
    idVendor:                        0x0CAD = Motorola GEMS
    idProduct:                       0x9011
    bcdDevice:                       0x2416
    iManufacturer:                     0x01
         English (United States)  "Motorola"
    iProduct:                          0x02
         English (United States)  "Motorola Tetra Radio"
    iSerialNumber:                     0x00
    bNumConfigurations:                0x01
    
              ===>Configuration Descriptor<===
    bLength:                           0x09
    bDescriptorType:                   0x02
    wTotalLength:                    0x0037  -> Validated
    bNumInterfaces:                    0x02
    bConfigurationValue:               0x01
    iConfiguration:                    0x03
         English (United States)  "Generic Serial config"
    bmAttributes:                      0xC0  -> Bus Powered
    MaxPower:                          0x00 =   0 mA
    
              ===>Interface Descriptor<===
    bLength:                           0x09
    bDescriptorType:                   0x04
    bInterfaceNumber:                  0x00
    bAlternateSetting:                 0x00
    bNumEndpoints:                     0x02
    bInterfaceClass:                   0xFF  -> Vendor Specific Device
    bInterfaceSubClass:                0x00
    *!*CAUTION:    This appears to be an invalid bInterfaceSubClass
    bInterfaceProtocol:                0x00
    iInterface:                        0x00
    *!*CAUTION:  0xFF is a prerelease Class ID
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x01  -> Direction: OUT - EndpointID: 1
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Interface Descriptor<===
    bLength:                           0x09
    bDescriptorType:                   0x04
    bInterfaceNumber:                  0x01
    bAlternateSetting:                 0x00
    bNumEndpoints:                     0x02
    bInterfaceClass:                   0xFF  -> Vendor Specific Device
    bInterfaceSubClass:                0x00
    *!*CAUTION:    This appears to be an invalid bInterfaceSubClass
    bInterfaceProtocol:                0x00
    iInterface:                        0x00
    *!*CAUTION:  0xFF is a prerelease Class ID
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x82  -> Direction: IN - EndpointID: 2
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
              ===>Endpoint Descriptor<===
    bLength:                           0x07
    bDescriptorType:                   0x05
    bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
    bmAttributes:                      0x02  -> Bulk Transfer Type
    wMaxPacketSize:                  0x0200 = 0x200 max bytes
    bInterval:                         0x00
    
    

    The device actually sends 0xFF for InterfaceClass. I would expect 0x02 for CDC.

    Marc

  • Surely, the device has two interfaces (composite device). Both of interfaces belong to vendor specific class (bInterfaceClass: 0xFF).

    The Vendor ID (VID: idVendor) shows it's a Motorola device.
    Is it an Android phone or pad?

    Android phone swaps its USB interface, when USB tethering is enabled on Setting.
    RNDIS (derivative of CDC) interface appears.

    Tsuneo

  • Hi, Marc!

    I wolud like to know if you have figured out some way to develop your CDC USB host driver;

    What did you do? Have you edited the USB MSD's files to adapt to a CDC like Tsuneo did recommend?

    Thank you in advance;

    Marcel.