I'm having trouble understanding how to use WriteEP on Bulk IN endpoints reliably, in particular how to recover from errors. My USB vendor class firmware (and basic understanding) is based on the USBD CDC example from the LPCOpen library for the LPC XPresso 1769 Evaluation Board.
My general understanding is that the application sends a packet to the host by calling WriteEP and then waits for the USB_EVT_IN event indicating a successful transmission before sending the next packet. If the host application (libusb in my case) is constantly checking for data at this endpoint everything is nice and well.
I'm observing the problem that if the host, for whatever reason, is currently not polling for data the communication blocks indefinitely even when trying to read the data at some later time. So what I did/observed is:
- Host: Application is idle and is currently not submitting bulk read requests.
- Device: Call WriteEP and wait for USB_EVT_IN.
- Host: Some seconds later a bulk read request is issued.
- Device: No USB_EVT_IN or any other kind of event appears at the EP handler.
- Host: Libusb reports read timeout.
- Device: No further data is sent because there are no events.
So the problem is that the LPC USB stack may give up on sending a packet written by WriteEP and seemingly doesn't provide a way to inform the application or recover from this state. The CDC example application doesn't really address this issue, but instead uses a workaround: It won't call WriteEP until a host CDC driver is detected which will usually continue to read/buffer IN data even if the data isn't read from userspace.
I'm looking for a way to detect and handle this situation correctly. How to detect when the USB stack "gave up" sending a packet?
How to clear the bulk endpoint buffers when recovering from such a situation? I observed that when I force WriteEP even with no prior USB_EVT_IN acknowledgement the data transmission indeed continues but the packet order at the host is getting mixed up.