libopencm3 / libopencm3-examples

Simple example projects showing how to use libopencm3.
482 stars 327 forks source link

USB CDC example for stellaris-ek-lm4f120xl not working under WinXP/Win7 #14

Closed Garag closed 11 years ago

Garag commented 11 years ago

Hello, i have tested the cdc example for the stellaris-ek-lm4f120xl board under Windows. When i plug USB the device gets enumerated (with a patched inf file) and all seems good. But when i try to open the device with a terminal program i am getting an error.

The Problem seems to be a USB_CDC_REQ_SET_LINE_CODING with databits set to 0. As this is invalid the function cdcacm_control_request() returns 0 and the transfer will be stalled.

So i am unsure how to handle the bad USB_CDC_REQ_SET_LINE_CODING request. Maybe ignore the bad databits setting return with no error.

If desired i can make a pull request.

mrnuke commented 11 years ago

The specification requires bDataBits to be either 5, 6, 7, 8, or 16. If the host sends a packet with bDataBits of 0, then that is an invalid packed, and the device correctly rejects it by stalling the pipe.

See "Universal Serial Bus Communications Class Subclass Specification for PSTN Devices, Revision 1.2, February 9, 2007", page 25.

Garag commented 11 years ago

I know that the behavior of Windows is not standard conform. But it is also frustrating if you try an example and it doesn't work. I was lucky that i have access to a USB analyser. So it was not a big deal to find the problem. Maybe a little hint in the readme is ok for you.

For me it is ok to stick to the specification and left the example as is.

mrnuke commented 11 years ago

USB analyzer or Wireshark should work. I don't know how the Windows driver model works and how they changed it since I last looked at it, but sounds like an issue with the *.inf file.

Feel free to submit a pull to update the README.

Garag commented 11 years ago

I think it is not a problem with the inf file. The CDC device gets enumerated and a serial port is available. As soon as i try to open the serial port Windows send a bad SET_LINE_CODING with only the baudrate valid. If the device rejects the request after some retries Windows fails with an error. If the request is acceted Windows will send more SET_LINE_CODING requests with correct values.

I dont like such workaround as the the windows driver do not conform to the standard. But i need it to work under Windows. I am open for better solutions.

mrnuke commented 11 years ago

I see three options:

  1. File a bug report with microsoft.
  2. Ignore bad packet in your project, but don't STALL the endpoint.
  3. Write a custom driver.

However, I would rather not merge non-compliant code in the examples dir. The SetLineCoding request is optional for CDC ACM, so I have no idea why windows just quits when it STALLs.

mrnuke commented 11 years ago

If you can upload USB capture files (PCAP format) to somewhere public, I'd be interested to have a look.

Garag commented 11 years ago

Is Wireshark under Windows able to capture USB ?

mrnuke commented 11 years ago

AFAIK, you need to capture it with winpcap, and Wireshark will be able to open the capture file postmortem. I don't know if there is a faster method to do this natively.

Does your USB analyzer software support exporting to pcap format? That might be easiest for you.

Garag commented 11 years ago

Currently i am at home. I will try with USBpcap and Wireshark at home. Tomorrow i can hava a lokk at the USB analyzer.

mrnuke commented 11 years ago

Last time I had to do this kind of stuff, I used a linux host with windows VM, and just used usbmon on the host with Wireshark.

Garag commented 11 years ago

Now there is USBpcap for Windows. I have captured to files.

  1. lm4f_example_error.pcap (http://www.everwait.de/usb/lm4f_example_error.pcap)
  2. lm4f_example_always_ack.pcap (http://www.everwait.de/usb/lm4f_example_always_ack.pcap)

The first is the original example and the second returns always ok on SET_LINE_CODING .

Garag commented 11 years ago

Tomorrow i will try to export the data from the USB analyzer. I think the output from the analyzer is much better.

mrnuke commented 11 years ago

Crap. winpcap didn't capture the setup packets. Can't tell what usbser.sys tried to do with all those SetLineCodingRequets. I suspect it is probing the capabilities, but that is a very wrong way to do it.

Garag commented 11 years ago

The export capabilities of the analyzer software are not very helpfull. I will attach a screenshot of the captured data. The capture shows two tries with different baudrate. The SET_LINE_CODING requests are expanded in the view.

Hope that helps.

openfailed

mrnuke commented 11 years ago

Yeah. Just what I thought. It tries 115200 baud, and when that fails, 9600 baud. It probes the supported capabilities one at a time. They must have figured that since 0 is a valid value for bCharFormat and bParityType, it should be valid for bDataBits, which is of course, a bad assumption.

I'm curious about the capture when the device doesn't stall.

Garag commented 11 years ago

Not Windows is probing. I have probed with two different settings. When i try to open the port with 115200 Windows returns an error and i am unable to open the port.

mrnuke commented 11 years ago

It sends a GetLineCoding request right after the failed SetLineCoding request. This is what we call the

i=5; i=5; i=5; //Make sure i is 5 or the code below will crash

syndrome. The STALL is meant to indicate that that the request has failed, so asking the device for the parameters is futile, since no parameters were set in the first place. GetLineCoding is also sent more than once, perhaps in the hope that the device has not yet had time to respond, but will do so soon in the future. This tells me that whoever wrote the usbser.sys driver did not understand USB and the CDC ACM protocol well enough.

The obvious solution is to set bDataBits to 8 if it is received as 0, but since this violates the official protocol, I would rather not have this in the example. Documenting the stupid things that some OSes do, along with a small set of modifications that could be done to make the device work is the preferred option. It should eliminate the frustration of "it doesn't work" because we know "how to make it work".

Garag commented 11 years ago

Document the stupid things is for me the best solution. It is better the example do not violate the standard. Thank you for your patience and help.