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 descriptor problem

Hello.

First of all, I want to say that I don't know if this is the right forum to do the question, but after days searching in the web, reading papers and changing the code, I'll try to explain my dude here.

I'm programming a device, with a USB communication in order to communicate with PC. I use an ATmega1281 with MAX3420 as USB controller. I get the windows recognize the device as COM Port...but I can only send or only receive data. If I try to set number of endpoints to 2 in the Data Class Interface descriptor, windows return an error (code 10), and can't initialize the device.
Here I show the configuration descriptors I use. Thank you for your time in advance! and regards.

const unsigned char CD[]=
// CONFIGURATION Descriptor
{ 0x09,// bLength
0x02,// bDescriptorType = Config
67,0x00,// wTotalLength(L/H)
0x02,// bNumInterfaces = 2
0x01,// bConfigValue
0x00,// iConfiguration
0xC0,// bmAttributes. b7=1
0x32,// MaxPower is 100 ma

// INTERFACE Descriptor
0x09,// length = 9
0x04,// type = IF
0x00,// InterFace Number = 0
0x00,// bAlternate Setting
0x01,// bNum Endpoints = 1 IN
0x02,// bInterfaceClass = 2 Communication
0x02,// bInterfaceSubClass = 2
0x01,// bInterfaceProtocol =1 (SubClass ACM,V.25ter)
0x00,// iInterface
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
0x05,// bFunctionLength, Descriptor size in bytes
0x24,// bDescriptorType, CS_INTERFACE
0x00,// bDescriptorSubtype, Header Functional Descriptor
0x10,0x01,// bcdCDC

// Abstract Control Management Functional Descriptor
0x04,// bDescriptorLength, Descriptor size in bytes
0x24,// bDescriptorType, CS_INTERFACE
0x02,// bDescriptorSubtype, ACM Functional Descriptor
0x06,// bmCapabilities

// Union Functional Descriptor
0x05,// bFunctionLength, Descriptor size in bytes
0x24,// bDescriptorType, CS_INTERFACE
0x06,// bDescriptorSubtype, Union Functional Descriptor
0x00,// bMasterInterface
0x01,// bSlaveInterface0

// Call Management Functional Descriptor
0x05,// bFunctionLength, Descriptor size in bytes
0x24,// bDescriptorType, CS_INTERFACE
0x01,// bDescriptorSubtype, Call Management Funct.Desc.
0x03,// bmCapabilities
0x01,// bDataInterface

// Endpoint Descriptor EP3-IN
0x07,// bLength
0x05,// bDescriptorType (Endpoint)
0x83,// bEndpointAddress (EP3 IN)
0x03,// bmAttributes (interrupt = 3)
0x40,0x00,// wMaxPacketSize
0x02,// bInterval, Maximum latency

// INTERFACE Descriptor
0x09,// length = 9
0x04,// type = IF
0x01,// InterFace Number = 1
0x00,// bAlternate Setting
0x01,// bNum Endpoints = 2 (IN&OUT)
0x0A,// bInterfaceClass = A (Data)
0x00,0x00,// bInterfaceSubClass, bInterfaceProtocol
0x00,// iInterface

// Endpoint Descriptor EP2-IN
0x07,// bLength
0x05,// bDescriptorType (Endpoint)
0x82,// bEndpointAddress (EP2-IN)
0x02,// bmAttributes (bulk = 2)
0x40,0x00,// wMaxPacketSize (64[0x40])
0x00,// bInterval

// Endpoint Descriptor EP1-OUT
0x07,// bLength
0x05,// bDescriptorType (Endpoint)
0x01,// bEndpointAddress (EP1-OUT)
0x02,// bmAttributes (bulk = 2)
0x40,0x00, // wMaxPacketSize (64[0x40])
0x00,// bInterval
};

Parents Reply Children
  • Sorry, but my project is not using the MAX3420 as used by the other authors.
    It could be nice to hear from others if they change the EP0 max packet size to 32 to see if they experience the same problem.

    /Peter

  • Hello Peter,

    "I found out that my EP0 max packet size was set to 32 bytes... These were transferred correctly and host responded with SetConfiguration, but the communication flow stopped!?!
    After changing EP0 packet size to 64 the CD was split into 64 and 3 bytes, but now the communication flow continued as wanted."

    Which request stops the enumeration?
    Find it out with a bus analyzer.
    If you don't have a hardware analyzer, download this software sniffer and 'evaluate' it :-)

    SourceUSB - 1 month trial
    http://www.sourcequest.com/

    As you see SetConfiguration, I don't think GetDescriptor( Config ) is not the problem. Maybe the problem lies on other request handling.

    Tsuneo

  • Hi,

    I am facing another problem with my CDC. After set_control_line_state status packet from host, the next interrupt I receive is an interrupt IN. This is followed by bulk IN interrupt. What am i supposed to sent as reply to these? can i just STALL them?

    After I open the hyper terminal, there occurs 4 get_line_coding, 1 set_line_coding, 1 set_control_line_state, 1 set_line_coding and again 1 get_line_coding? Are all these expected or is it coming because of some firmware issues? After all this, no more transactions occur. No bulk IN or bulk OUT. When i press characters on the hyper terminal; on the software analyser I see a bulk out transaction started but then CANCELLED.

    I am really goin crazy over this. Any help will is highly appreciated.

  • Hello Arun,

    Sorry, I missed your previous post,

    "You mention that you reply to SET_CONTROL_LINE_STATE setup command from the host using the interrupt endpoint (which is 3 IN in your case). What is the exact reply you post to host? Is it NETWORK_CONNECTION status?

    Also after you send the reply, you mention that a ZLP has to be sent. Is it from device to the host? Is it on control endpoint (EP 0 IN)?"

    SET_CONTROL_LINE_STATE request and the interrupt IN endpoint has no relation. Nor bulk IN endpoint. Handle these request and endpoint independently.

    1) SET_CONTROL_LINE_STATE requuest
    The handling of SET_CONTROL_LINE_STATE finishes like other requests.
    a) The SETUP packet is parsed and the execution enters to SET_CONTROL_LINE_STATE handler.
    b) In this handler, the handshake lines are changed following D0(DTR) and D1(RTS) of wValue.
    c) At the STATUS stage of this request (control transfer), ZLP is sent back to host over the default endpoint, to show success.

    SET_CONTROL_LINE_STATE is carried over no-data control transfer.
    SetConfiguration, ClearFeature and SetFeature requests are also no-data control transfer. You'll write the SET_CONTROL_LINE_STATE handler similar to the handler of these requests. Just the job of the request, ie. above b) part, is different.

    2) Interrupt IN endpoint
    Over this endpoint, the firmware returns SerialState notification. This notification is sent to host just when DSR is changed on the device. Or other signaling, DCD and error flags (overrun, parity, frame), are changed.

    6.5.4 SerialState (PSTN120.pdf p32)
    www.usb.org/.../CDC1.2_WMC1.1.zip

    The hardware interrupt of this endpoint is not a good place to handle this process. A typical implementation is,
    In a timer (or SOF) interrupt, check the state of DSR, DCD and error flags. If there are any state change, make up SerialState data block and fill it to the interrupt IN endpoint.



    "After I open the hyper terminal, there occurs 4 get_line_coding, 1 set_line_coding, 1 set_control_line_state, 1 set_line_coding and again 1 get_line_coding? Are all these expected or is it coming because of some firmware issues?"

    It's the normal (?) sequence of Windows usbser.sys device driver. :-)

    "After all this, no more transactions occur. No bulk IN or bulk OUT."

    Actually, bulk IN-NAK transaction occurs repeatedly on the bus, but software sniffer can't see this traffic. Just hardware analyzer does.

    "When i press characters on the hyper terminal; on the software analyser I see a bulk out transaction started but then CANCELLED."

    Do you read out the bulk OUT endpoint in the interrupt handler of this endpoint?

    Tsuneo

  • hi, Mr Tsuneo Chinzei
    do you ever build an cdc device? have you tested it?
    several days ago i build it, and now it's works. but my device is not full duplex. if i send data from VCOM to UART(microcontroller, UART TX) and as soon after it ,i send data from UART (microcontroller received data/ UART RX), so the communication is hang. but if only transmitted or received, my device is ok. can you give advice how i can make full duplex?? i ever try with interrupt (RX) and polling (TX), but it's to many data error .

    thanks for your help

  • how i can avoid buffer overrun when using usb-cdc? i have tested usb-cdc from many site, but if i countinuous send data full duplex from microcontroller and loopback again to PC, sometimes my microcontroller hang after 3-4 minutes(i using 9600 baudrate, 8-N-1), for transmitting - loopback 32.768Kbytes takes time +-34 s. (3 minutes=180s, 180/34 ~ 6 x[32Kbytes]. i using interrupt for transmitting and receiving, 256 bytes buffer for RX, 128 bytes for TX. when i change this size (both RX and TX buffer) this problem still occur. i have debug and the problem is buffer overrun. I try to monitor usb transaction with USB protocol analyser "usblyzer" (http://www.usblyzer.com), i found report with ...buffer overrun. what i should do?? any suggestion how to add timeout for bulk in transaction??(receive UART-RX and send back to USB host). or maybe any other idea to solve this problem?

    thank you

  • "how i can avoid buffer overrun when using usb-cdc?"

    Send ZLP after 32.768Kbytes transfer to the bulk IN endpoint.

    Windows CDC device driver, usbser.sys, doesn't finish bulk IN transfer until you send a short packet. Short packet means a packet whose payload is less than wMaxPacketSize (usually 64), including zero (Zero-Length Packet: ZLP). As 32.768Kbytes is just the multiple of 64, you have to send ZLP.



    Another point is,
    Using SetupComm(), increase the RX buffer size on the device driver to fit to the transfer size.

    "SetupComm Function" on MSDN
    msdn.microsoft.com/.../aa363439(VS.85).aspx



    If you are working on VB6 MSCOMM using onComm_event, another usbser.sys problem arises. See this post

    "CDC transmitt delay" on Microchip USB forum

    If you directly connect bulk OUT EP to bulk IN EP, this calculation doesn't work. These bulk pipes works unrelated to baudrate. You'll see much faster transfer speed.

    "define start bit ?" on Microchip USB forum
    forum.microchip.com/tm.aspx

    Tsuneo

  • thanks Tsuneo Chinzei,
    i was try add ZLP and increase the RX buffer size on the device driver to fit to the transfer size, but sometimes "buffer overrun" problem still occur. i was try using thesycon cdc driver, and this problem still happen, but transfer rate more faster (+-9%). i try to loopback using my software serial terminal (i develop for myself using .net). the loopback procedure is every byte sent from pc (COM port, ex COM1 --> Virtual COM port, ex COM2)will transmitted back to pc (Virtual COM port,COM2 --> COM port, COM1) i looback from software on PC, not in microcontroller. any suggestion? thank you

  • Bamb,

    There are four buffers on the CDC implementation, on the firmware and PC device driver. Until you specifies the buffer which causes overrun, I can't tell the exact cause. As you didn't specify the MCU and the USB CDC example on which you are based, I can't tell which one is which.

    - Which MCU and example are you working on?
    - Which buffer do you see buffer overrun?

    Tsuneo

  • I've seen two types of buffer naming on CDC implementations on device side.

    a) Named after the connection
    bulk OUT EP ---> TX buffer ---> UART TX
    bulk IN EP <--- RX buffer <--- UART RX

    b) Named after the function on the device
    bulk OUT EP ---> RX buffer (receive data)
    bulk IN EP <--- TX buffer (send data)

    Then, until you specify the example you are working on, our discussion will go out of focus.

    Tsuneo

  • Hello Tsuneo
    I have followed your discusion around the CDC descriptor problem. This was very useful info to me, but never the less i got stuck.

    I have come so far that i get the enumeration to work.

    Now to my problem.
    If i try to connect with hyper terminal i get an error on my USB analyzer (the one you recommended above) with the following commands
    when I try to change rate: get_line_command => IRP status = NO_SUCH_DEVICE and URB status = USBD_STATUS_INVALID_PARAMETER. set_control_line_state => IRP status = NO_SUCH_DEVICE and URB status = USBD_STATUS_INVALID_PARAMETER.

    The same happens if i try to send a file to the device Bulk_or_interupt_transfer => IRP_status = INVALID_PARAMETER and URB status = USBD_STATUS_INVALID_PARAMETER.