We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I am useing a AT91SAM7 microcontroller with Keil Realview compiler and USB HID. My code is based on the example code of the Atmel SAM7-EK Board.
Does anybody know what to do, when the uController has no data to send and get's a request from the host to send something. When the PC has noting to send I do not get an SAM7-uC USB interrupt for the Interrupt In Endpoint. However for the HID Interrupt Out Endpoint I get interrupts all the time. If I do not send any data when I get the interrupt the communication Device to Host doesn't work properly because if I reply a few times with some data and then stop to reply and then read the data from the host input buffer of the PC using the visual C++ V6 HID USB api it reports some error. If I send the same data all the time on a request it works. I could send some dummy data if I have nothing to send but that fills the PCs HID report input buffer and if it doesn't respond quickly enough data gets lost.
So now what to do?
"You have to apply asynchronous (OVERLAPPED) ReadFile(), because synchronous ReadFile() blocks the thread, until the device returns input report."
Is this really a requirement? OVERLAPPED is an efficient way to avoid the blocking, but another way to let an application to continue while waiting for data is to split it into multiple threads. Then it doesn't matter if one thread hangs waiting for data - the rest of the application can do whatever tasks that needs to be done, and when data arrives, the communication thread can read it and update relevant data structures.
"but another way to let an application to continue while waiting for data is to split it into multiple threads."
In principle, you are right. In these reasons, however, the combination of sub-thread and synchronous call is not used.
a) Thread termination While the thread is blocked by the synchronous ReadFile, these calls are not canceled by CancelIo(). Then there is no way to terminate this thread at the end of the application. It means, the application doesn't finish unless any input comes from the device.
CancelIo Function msdn.microsoft.com/.../aa363791.aspx "Cancels all pending input and output (I/O) operations that are issued by the calling thread for the specified file. The function does not cancel I/O operations that other threads issue for a file handle."
b) Error handling Synchronous ReadFile/WriteFile often get stuck on surprised removal of USB device.
Then, OVERLAPPED call is applied in the sub-thread, too. And WaitFor- function is used to make the thread sleep.
Tsuneo
Thanks. Yes, I have seen a number of Win application locking up after removing USB devices. This may be the reason why.
My standard code for serial communication is using overlapped transfers, but I haven't written any USB code yet, and wanted to know my available options.
Thank you for your answers so far. I managed to get it working by disableing the interrupt Out Pipes endpoint handler in the uC.
Now I have another problem. I have defined several Report IDs. When I send data on the interrupt Out pipe - and only want to send the amount of bytes - how to do it.
I tried:
if (WriteHandle != INVALID_HANDLE_VALUE) { Result = WriteFile (WriteHandle, OutputReport, REPORTSIZE, //Capabilities.OutputReportByteLength, &BytesWritten, NULL); }
useing REPORTSIZE as the reportsize corresponding to the ReportID which is smaller size than the largest Report ID (max is Capabilities.OutputReportByteLength)
I get a message - the referenced User Buffer is not allowed ... Can't write to device
What have I done wrong?
Hello again,
I think I have found the solution myself. Windows always reads the complete buffer with length Capabilities.???ReportByteLength like Capabilities.InputReportByteLength. The lenth returned by the write function has nothing to do with the number of bytes acutally transferred over USB. It is always the maximum size of that report type ...
"I managed to get it working by disableing the interrupt Out Pipes endpoint handler in the uC."
I think it's IN pipe. You are still mixing up IN and OUT :-) "useing REPORTSIZE as the reportsize corresponding to the ReportID which is smaller size than the largest Report ID (max is Capabilities.OutputReportByteLength)
I get a message - the referenced User Buffer is not allowed ... Can't write to device"
For HID device I/O, use always Capabilities.OutputReportByteLength for nNumberOfBytesToWrite parameter of WriteFile. The OutputReportByteLength holds the greatest length of the output report. Also the buffer handed to WriteFile should have this size. But you don't need to fill the buffer with padding bytes. Just fill it with the size determined by the report ID.
It's Windows HID feature. I don't know the reason why MS have designed the API like this.
They may consider to write multiple reports at a time using an OUT buffer on the device driver, though it is not implemented so far.