Author Topic: Full duplex HID  (Read 23317 times)

dpenney

  • Member
  • ***
  • Posts: 8
Full duplex HID
« on: October 04, 2012, 06:54:02 pm »
Hello,
I am somehow dropping some reports during my attempt at duplex HID communcations.  My best theory at the moment is that a WriteFile() will clear the HID driver buffer of any cached input reports that have not been retrieved by ReadFile() yet.  Is that correct?  (If so, I don't know why it should, it seems like there should be separate read/write buffers.)

Here is my pseudo-code, it mostly writes Output Reports and looks for the occasional Input Report:
do
    do while OverlappedResult(for write) == %FALSE : loop
    load some app data into WriteFile() buffer (a different buffer than the ReadFile() buffer)
    WriteFile() (overlapped)

    if GetOverlappedResult(for read) {
        ReadFile() (overlapped)
        display the Input Report from the ReadFile() buffer  (a different buffer than the WriteFile() buffer)
    }
loop

This always misses the 2nd of a pair of Input Reports sent from the other machine.  If 1) I take out the WriteFile() above, or 2) add delay before sending the 2nd report from the other machine, then the ReadFile() above catches both Input Reports correctly.

Thanks,
dpenney

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Full duplex HID
« Reply #1 on: October 05, 2012, 10:23:57 am »
The WriteFile and ReadFile buffers are independent unless your application is using the same buffer for both.

If the device is sending data in response to received data, it should load the IN buffer only after receiving data at the OUT endpoint.

This is because the host sends OUT packets only after a WriteFile, but it sends IN packets continuously according to the max latency requested in the endpoint's descriptor.

dpenney

  • Member
  • ***
  • Posts: 8
Re: Full duplex HID
« Reply #2 on: October 05, 2012, 05:38:50 pm »
Jan, thanks for your reply.  I think my misunderstanding must be something very simple.

In order to try to isolate the issue, I took out the WriteFiles:

do
    if GetOverlappedResult(for read) {
        display it
        ReadFile()
    }
loop

and when I have the PIC device quickly send only 2 reports from to the computer, both are displayed correctly.

But then (instead of WriteFiles) if I add a Sleep to the loop above that is large enough, one of the Input Reports is missed.

do
    sleep 600  <---- causes the 1st Input Report (of 2) to be missed.

    if GetOverlappedResult(for read) {
        display it
        ReadFile()
    }
loop

I guess it would make sense to me if the HID driver buffer is latching continuously during the sleep and therefore finally dropping the 1st input report after it becomes full, but I don't see why it would be latching during this time if nothing is explicitly being sent from the device.

Is that what is happening?  Even if no new data is explicitly sent, the data must be unloaded from the HID driver buffer within a certain time or else it is lost?

Thanks,
dpenney

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Full duplex HID
« Reply #3 on: October 05, 2012, 09:16:39 pm »
If the second ReadFile returns report 2's data again, the device is likely sending a report on every IN token packet. After sending a report, the endpoint should return NAK until it has a new report to send. See your controller's data sheet for details on how to configure the endpoint for this.


dpenney

  • Member
  • ***
  • Posts: 8
Re: Full duplex HID
« Reply #4 on: October 05, 2012, 09:28:54 pm »
GetOverLappedResult only fires once (and gives the 2nd Report).

If I remove the Sleep statement it correctly fires twice (and gives both Reports correctly).

So maybe it is not as simple a mistake as I thought!  I will try some other things and report back.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Full duplex HID
« Reply #5 on: October 05, 2012, 10:02:28 pm »
Be sure the host has retrieved the first report's data before filling the endpoint's buffer with the second report's data.

dpenney

  • Member
  • ***
  • Posts: 8
Re: Full duplex HID
« Reply #6 on: October 06, 2012, 01:02:46 pm »
I was previously unaware that ReadFile had timeouts associated with it and thought that must surely be my problem.

However, whenever I try to use the simple functions GetCommTimeouts() & SetCommTimeouts() just after CreateFile(), they return "Incorrect function" (API code is INVALID_FUNCTION).

Has anyone ever used these functions, are they somehow not usable for USB HID?

Thanks,
dpenney

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Full duplex HID
« Reply #7 on: October 06, 2012, 01:14:13 pm »
My HID example code implements timeouts with overlapped ReadFiles:

http://www.lvr.com/hidpage.htm#MyExampleCode

dpenney

  • Member
  • ***
  • Posts: 8
Re: Full duplex HID
« Reply #8 on: October 06, 2012, 01:54:19 pm »
Jan, thanks very much for the help.

In your example code, I only see timeouts asscociated with WaitForSingleObject.  Is that what you were referring to?

If I understand the MSDN docs correctly, the windows API functions GetCommTimeouts() & SetCommTimeouts() are intrinsically associated with ReadFile():

"When reading from a communications device, the behavior of ReadFile is determined by the current communication time-out as set and retrieved by using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable results can occur if you fail to set the time-out values. For more information about communication time-outs, see COMMTIMEOUTS."
(http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx)

In other places on the web, I have since found examples of using these statements with COM ports (not yet with USB though) but have been unable to get past "Incorrect function" when I try them.  Have I missed them in your code somewhere?

Thanks,
dpenney

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Full duplex HID
« Reply #9 on: October 06, 2012, 02:00:37 pm »
>In your example code, I only see timeouts asscociated with WaitForSingleObject.  Is that what you were referring to?

yes

>If I understand the MSDN docs correctly, the windows API functions GetCommTimeouts() & SetCommTimeouts() are intrinsically associated with ReadFile():

>"When reading from a communications device, the behavior of ReadFile is determined by the current communication time-out as set and retrieved by using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable results can occur if you fail to set the time-out values. For more information about communication time-outs, see COMMTIMEOUTS."
(http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx)

"communications device" means COM port.


dpenney

  • Member
  • ***
  • Posts: 8
Re: Full duplex HID
« Reply #10 on: October 08, 2012, 10:29:43 am »
>>"communications device" means COM port.

That explains why my functions failed!  Thanks Jan, I appreciate your time and help.