I am implementing a simple USB command response interface for the PsoC 4 board I designed. I have it working but only through a nasty workaround.
In the CyUSB,NET document it states that ReadInput() will indefinitely hang until a input report is received. I immediately noted that it
does not hang but simply reports a packet of all zeroes. To make it work I had to add a Thread sleep of 16 or greater ms after the WriteOutput() function
sends a command. My device has a generic HID interface with 8 byte packets. This fix is problematic because of varying times for the device
to send it's response. Sometimes, I have to wait 32, 48 or even 64ms to receive a valid response.
Why does ReadInput() not block as stated ? Also, is there another function I can call to guarantee the response packet has been received before I post
a ReadInput() ? I noticed there is a WaitForXfer function in the EndPoint class hierarchy. But nothing like that for CyHIDDevice.
And, what happens if the device never responds? You could have the code indefinitely waiting for "nothing".
A good approach would be to have a best-effort time where you are actively expecting a response and waiting/checking for it (say 2-5 seconds depending on your application), and if the packet is not received within that time frame, then the device either restarts, cancels, or fails depending on application.
It sounds like the ReadInput() function doesn't wait, but rather returns the structure with the "last received" data which could be all zeroes for no data received? If that is the case, then you can ReadInput(), check if response or not, wait x ms, then try again until maximum timeout is reached.
The definition of a blocking Read is exactly that it will hang indefinitely if no response is received. The way you usually handle that is
by wrapping it in a timeout of say 1 second.
Since my board is the only device at the address on USB I am sending commands to, I know there will be no unknown packets of all zeroes since I never send one. This means ReadInput() is returning when no transaction has occurred. Not sure why.
I have some commands that expect a response (sometimes lots of responses) and some that expect no response. I don't call
ReadInput when I send a command that requires no response.
I tried screening out packets of all zeroes but that doesn't work either. The CyUSB User Manual states that sync comm is the easy
way to communicate rather than using async comm with BeginXfer/WaitXfer/FinishXfer. But there is no way I can find to accomplish
true sync communication as an HID device.
Command/Response is simple to handle since there are no async events to handle but it sounds like I may have to switch to an async model
where responses are not directly tied to commands. I would have to poll for responses using a timer. Unfortunately, that would change a lot of code on both the Host and the Device.
i was hoping there was a way to get an acknowledgement from CYUSB that a packet had arrived and then post the ReadInput(), that would be the simple solution, similar to looking at an interrupt to trigger a read.
If you find another approach, please let me know.
Thanks for your help,
Sounds like you have much better intimate knowledge of the Cy USB library. Well, best of luck
I do know that USB is designed to be packet-based, and thus having async packets makes sense.
I would expect there to be a USB response flag/trigger (at least for the OS if not for Cypress' api).
I have no intimate knowledge of CyUSB library other than reading the manual.
The USB is always polled by the Master (Host Controller) (even an "Interrupt" EndPoint)
so it's never truly asynchronous.
But that fact doesn't matter at all for implementing a simple Command/Response interface.
On the device side (my custom PSoC4 SUB board) to receive a packet from the Host i do this:
/* Check to see if the OUT Endpoint is full from a received command packet */
if(USBFS_GetEPState(OUT_ENDPOINT) == USBFS_OUT_BUFFER_FULL)
/* Get the number of bytes received */
out_count = USBFS_GetEPCount(OUT_ENDPOINT);
/* Read the OUT endpoint and store data in out_report */
out_count = USBFS_ReadOutEP(OUT_ENDPOINT, out_report, out_count);
Just would like to have an equivalent way on the Host side to do the same, i.e.
post a ReadInput() AFTER I get some kind of buffer full (or packet ready) acknowledgement.
This ain't rocket science. It's standard programming practice in all communications.
Maybe someone in the community understands what I'm talking about here.
Not trying to be insulting or coy, just trying to solve what I thought to be a simple problem.
No offense taken (And non given I hope)
I have worked with the BLE and wireless PSoCs mostly, so the USB/Cysmart applications are more executables from my perspective.
I understand that what you are asking/want is common for CSci, but I don't know what the library supports/does 😕
I do know that from what I've seen of the Cypress APIs on the hardware, there are common functions missing here and there, so it might be possible that the handshake approach to the USB communications isn't implemented, or at least not directly.
Checking the return value will give an indication if there is an error, but I doubt it will give a "data received" response or flag like you want.
CyUartRead is the closest I can find, but it is the same as what you were stating for ReadInput().
This page is where I'm reading it: http://www.cypress.com/documentation/software-and-drivers/usb-serial-software-development-kit
Asking one of the Cypress employees or opening a case might be your best bet
It looks like Cypress has sent info to elevate this to a case. So I'll try that path, Thanks for your help.