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 };
"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."
I don't see any error (except for the number of EP) on the descriptors.
Disconnect the device from the PC, On the Device Manager, delete the device instance of this CDC once. Then, re-install the device. You can see disconnected device on the Device Manager as follows.
1) Copy these two lines to a blank text file, and rename the file to DevManager.bat
set devmgr_show_nonpresent_devices=1 start devmgmt.msc
2) Double click DevManager.bat, and Device Manager comes up. On 'View' menu, select 'Show hidden devices'
CDC device is displayed under "Port (COM & LPT)" branch on the Dev Manager. The CDC device requires custom INF file to install to the PC. Is there any problem on the INF file?
You can see working INF file in this example (USB_CDC_skeleton_15.zip) on my post to SiLabs forum. "USB CDC implementation for 'F32x & 'F34x" on SiLabs USB forum www.cygnal.org/.../000945.html
Modify the VID/PID of the INF file, to that on the device descriptor of your device.
Tsuneo
Hello!
I tryed quickly to do what you say and it seems that not work...but the device is halted, windows doesn't return any error code. I want to see it with calm, and try again. I will tell you if it works.
Thank you very much in advance for your time!
Regards, Rubén.
Hello Tsuneo!
Now I solved one problem, but I'm not satisfied at all...because I can't understand where were the error and there are new problems...
Related with descriptor length. Yes, I do what you comment: I send the requested length if it's lesser than configuration descriptor length, or total length of configuration descriptor, if requested length is greater. But in the case of the 19 bytes requestes, I must send header functional desc., call management functional desc., abstract control management desc., and union functional descriptor ('Class Headers' to short from now on). If I send configuration descriptor without take care of boundary, enumeration stops, and windows return error and can't use the device.
Frame 13 is 'set control line status' not 'set line coding '(it was my fault :P). Anyway, now I can read 'set line coding correctly' (thanks!) and I can see that USB send me the configuration I use in my host software. It's not important, but it makes me happy to know that it's working fine ;).
As I suspected, the problem was in the sent configuration descriptor. When I send the descriptor, it was like if the host couldn't read last endpoint descriptor (only the first one of the 2 last endpoints was working fine). I suppose that my descriptor has 67 bytes of total length, and would be a problem to send 2 frames (64 bytes + 3). I can't see the error, but I'm sure that there is the problem.
As the 'Class Headers' are requested later individually, I put them at the end of the configuration descriptor in order to get that the host made a correct reading of endpoint configuration, and it works! I can use now the 2 endpoints at same time, and windows recognize the device...but I don't know why, I can only send 2 bytes to host by EP2. EP2 is a 64 bytes IN FIFO, double-buffered. When I charge the 2 buffers, it don't send anything more to the host. Sometimes the register tells me that FIFO is full, sometimes is free to charge new data, but it doesn't matters, because don't send the next data.
Well, lots of thanks for your attention again, you're very kind. I hope this post help more people, and if you, or anybody have any idea about the new problem...I would be very grateful.
Regards! Ruben.
I monitored my CDC implementation on a hardware bus analyzer. This is the result.
CDC-ACM (port) enumeration sequence WinXP SP2, SP3 wValue wIndex wLen Bus Reset Get_Descriptor(DEVICE) 0x0100 0x0000 0x0040 Bus Reset Set_Address 0002 0000 0000 Get_Descriptor(DEVICE) 0100 0000 0012 Get_Descriptor(CONFIG) 0200 0000 0009 Get_Descriptor(STRING) 0300 0000 00FF Get_Descriptor(STRING) 0303 0409 00FF Get_Descriptor(CONFIG) 0200 0000 00FF Get_Descriptor(STRING) 0300 0000 00FF Get_Descriptor(STRING) 0302 0409 00FF Get_Descriptor(STRING) 0300 0000 00FF Get_Descriptor(STRING) 0302 0409 00FF Get_Descriptor(DEVICE) 0100 0000 0012 Get_Descriptor(CONFIG) 0200 0000 00FF Set_Configuration 0001 0000 0000 Get_Line_Coding 0000 0000 0007 Set_Control_Line_State 0000 0000 0000 IN transaction to the Interrupt IN EP Vista SP1 wValue wIndex wLen Bus Reset Get_Descriptor(DEVICE) 0x0100 0x0000 0x0040 Bus Reset Set_Address 0002 0000 0000 Get_Descriptor(DEVICE) 0100 0000 0012 Get_Descriptor(CONFIG) 0200 0000 00FF Get_Descriptor(STRING) 0303 0409 00FF Get_Descriptor(STRING) 0300 0000 00FF Get_Descriptor(STRING) 0302 0409 00FF Get_Descriptor(DEVICE) 0100 0000 0012 Get_Descriptor(CONFIG) 0200 0000 00FF Set_Configuration 0001 0000 0000 Get_Line_Coding 0000 0000 0007 Set_Control_Line_State 0000 0000 0000 IN transaction to the Interrupt IN EP
Other than the device_qualifier (because of in-between hub), Frame No.9 and 10 are different from your observation. Your frame No.9 should be Get_Descriptor(DEVICE), with wLength =18 bytes, And No.10 Get_Descriptor(CONFIG) with wLength =255 bytes
Hello, Tsuneo.
I try to install USBlyzer in another computer with Vista Business, and it seems that works (in Vista Ultimate it doesn't work rigth, because any program that try to open the port tell that it can't be open or that is already used by another telephone program).
I can see that when I try to send by EP2 IN (bulk tranfer) any data the analyzer notify:
Type---Request--------------------Request Details URB----Bulk or Interrupt Transfer--4096 URB----Bulk or Interrupt Transfer--0
and after the second notification the Status=Unsucceful(Stall PID). Both IRP=84389C80H.
If I run program step by step, it returns the same except for the second notify:
Type---Request--------------------Request Details URB----Bulk or Interrupt Transfer--4096 URB----Bulk or Interrupt Transfer--11
and after the second notification the Status=Success(Success).
When I look at request summary, I can see the following comments about the first bulk transfer:
USB Bulk or Interrupt Transfer issued Device Object: USBPDO-7 Driver Object: usbhub URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER Endpoint 82h: 2 in, Bulk Buffer Length: 1000h (4096)
The second bulk notification when return unsuccseful:
URB Bulk or interrupt transfer failed all is the same except for. URB Status: USBD_STATUS_STALL_PID and there is no Buffer Length.
The second bulk notification whem return success:
USB Bulk or Interrupt Transfer succeeded all the same but, URB Status: USBD_STATUS_SUCCESS and, Bytes Received: 11
I don't know why debugging step by step it return a different values, maybe is related with communications speed?
Why after host return Bulk transfer succeeded don't let me start another bulk transfer?
Should I notifify a new serial status?
Now I will try to get enumeration frames in the USB analyzer. I don't know the reason why Vista send me different requests than you.
Regards.
When the sniffer reports STALL on the bulk-IN EP, your firmware actually STALL the EP. I think it is a bug on the firmware.
"maybe is related with communications speed?" "Should I notifify a new serial status?"
The bulk IN and OUT transfers of CDC is affected neither by the baudrate setting (Set_Line_Coding) nor by the Serial_State notification over the interrupt IN EP. The bulk IN and OUT transfers are controlled independently following to the USB intrinsic NAK flow-control.
Did you check your Frame No.9 and No.10 on the enumeration?
I check the frames with USb analyzer, and discover that were a problem with a configuration descriptor. Now I see that host don't ask me for a configuration descriptor of 160 Bytes, and it seems that there is no error in configuration descriptor. Anyway the behaviour of the device it's the same. Now, the frames I can see in the enumeration are:
1.Get Device Descriptor 128 6 0 1 0 0 64 0 Bus Reset 2.Set Address 0 5 1 0 0 0 000 0 3.Get Device Descriptor 128 6 0 1 0 0 018 0 4.Get Configuration Des. 128 6 0 1 0 0 255 0 5.Get String Descriptor 128 6 3 3 9 4 255 0 6.Get String Descriptor 128 6 0 3 0 0 255 0 7.Get String Descriptor 128 6 2 3 9 4 255 0 8.Get Device Qualifier 128 6 0 6 0 0 010 0 9.Get Device Descriptor 128 6 0 1 0 0 018 0 10.Get Configuration Des. 128 6 0 1 0 0 009 1 11.Get Line Coding 161 33 0 0 0 0 007 0 12.Set Control Line State 33 34 0 0 0 0 000 0
Frame Nº9 is Get Device Descriptor with length of 18, and the next Configuration descriptor with length of (109??). I thought this frame has a length of 19, and there was an error. Now I send all descriptors here and USB analyzer don't return an error. I don't understand why I only can send the first frame, and it don't works anymore...I see in the analyzer some frames OUT in EP 2, that is configured IN (and can't work as out), and is sent from host the following data:
1B DF 08 0A 00 00 00 0E 05 20 01 00 00 00 58 13 00 00 5F 29
These frames are not always identical, but are similar...
After spending a long time changing the code, I always get the same result:
it seems that the device send the first frame by EP2 (IN Bulk) after connecting with serial port, the length and data sent is correct.
After this frame, the 'response' is that the frame is 4096 Bytes length.
The next operation device realices is to send a frame by EP3 (IN, Interrupt) (I don't know why, I don't try to send any frame by this EP, but the Serial State when the device connects to serial Port), but the status report tells me 'USBD_STATUS_BUFFER_OVERRRUN'.
Finally, there appears another try of sending a frame by EP2 (IN, Bulk), but the status says: 'USBD_STATUS_STALL_PID'.
I'm sure there are an error in the code, when I try to send the data by EP2, but I can't see it. I try to make a 'data toggle' in EP3 some times, and it works...for one time and no more (I suppose it was a set of circumstances, a simple coincidence), but it makes me think that I'm doing something wrong in the protocol sending data? (and the device is configurated correctly).
Well, finally the problem is solved!
There was an error, after sending set_control_line_status by interrupt EP, device don't send a ZLP correctly due a firmaware error, it was all...uff...I almost go crazy :P.
Thanks for your attention, speccially for Tsuneo.
Hi, i'm student in indonesia. i have a final project, i will develop some embedded system application that works with usb. after +-2 month i learning max3420, i still can't reply host OUT request. can you help me? can you send me your code?
thanks a lot
suriva (suriva.25 at gmail dot com)
I read your message, and I'll post the reply as soon as possible.
Regards, RubeÂ'n.
Hello Rubén R, I'm doing simillar implementation with MAX3420. How did you manage to send the configuration descriptor of 67bytes. The EP0 (control End point) has 64 byte FIFO, it's look like sending anything above 64bytes is a problem. I can get the host PC to regonise the device by removing a functional descriptor (to make configuration descriptor is less than 64 byte). but that doesn't provide all the functions of the intented design.
please let me know how you overcome this issue.
Thaks for your time. Kind regards, Thanushan
This is exactly the same issue i am facing. 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)?
I am looking forward to the reply from you or Tsuneo. Thanks in advance.
Hi,
I also have some USB problems. I use the windows driver usbser.sys to make a CDC device
But if I add the Union Functional Descriptor (UFD) then then communication flow stops after SetConfiguration(1). If I remove the UFD then my communication works fine, but I don't think it is 100% USB compliant. Can anyone give me a hint to why the UFD make my communication flow stops? My target code is not stalled, but no data seem to be transferred from the host. My device/configuration/interface and endpoint descriptors are like already mentioned.
Thanks, Peter
After checking the problem Thanushan Bala have, I realized that it is not the UFD that is the problem, but the same as Thanushan Bala. Does anyone have a good explanation why the length of configuration descriptor should be less that 64 bytes?
Sorry for spamming the discussion, but I found a solution for my problem. I don't know why, but perhaps someone can give an explanation. I found out that my EP0 max packet size was set to 32 bytes. This split the configuration descriptor (CD) of 67 bytes into 3 IN transactions (32,32 and 3). 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. Now why is it a problem using EP0 max packet size of 32 byte?
Send me the code now and I will confirm the results.
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.
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?
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
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?
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.
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.
View all questions in Keil forum