Ports and Interfaces > USB

HID - Sending OUT Report while IN Report is Waiting

<< < (2/4) > >>

Jan Axelson:
yes

Victor M:
Jan, I believe I understand the implications of asynchronous calls, but with respect to that I notice in your example code the FileStream is opened with the async parameter set to false.


--- Code: ---_deviceData = new FileStream(_hidHandle, FileAccess.Read | FileAccess.Write, _myHid.Capabilities.InputReportByteLength, false);
--- End code ---

If I change it to true, the following exception happens - Additional information: Handle does not support asynchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened synchronously (that is, it was not opened for overlapped I/O).

The FileStream opened on _hidHandle does not support overlapped read/write. It seems full duplex operation may not be possible with HID using FileStream, at least not the way it's done in the example. However that does not prevent read and write methods from being called asynchronously, as indeed they are in the example.

In spite of the foregoing I was able to get it to work (somewhat) as follows:

The timeout for reading the IN report was set very short - 5ms. OnReadTimeout() closes communications (FileStream and Handle are closed). The timeout event however does not cause code execution to resume in RequestToGetInputReport(). Execution resumes only when an IN report has been received. When that happens, RequestToGetInputReport() is again called, causing a new FileStream to be opened.

While waiting for an IN report (none being received), an OUT report may be sent. A call to RequestToSendOutputReport() will also cause a new FileStream to be opened.

The thing worth noting is that the FileStream is being opened and closed continually as each IN reprot is received. I think this is not very desirable. Also there is another side effect - whenever an OUT report is sent, and then an IN report is received, there is a duplicate of the IN report. What's happening (I think) is the IN report causes execution to resume in RequestToGetInputReport(), and the report gets printed. Then RequestToGetInputReport() is called again (but with the newly instantiated FileStream), and the same report is again received. So I have to ignore the second report.

Question: Is there any way to establish an I/O connection between the application and USB host that is asynchronous overlapped so that data can be read and written without having to continually open and close the connection?

Jan Axelson:
I added the _transferInProgress variable because the example sends data, then waits for a response. If the Input and Output reports are independent, you can delete the instances of:

if (_transferInProgress)

Victor M:
Jan,

If there is a pending call to get an IN report, and I try to send an OUT report (ignoring _transferInProgress) the program hangs. There is no exception thrown. In the code below (Hid.cs) I put a breakpoint at

Task t = fileStreamDeviceData.WriteAsync(outputReportBuffer, 0, outputReportBuffer.Length, cts.Token);

and the breakpoint is hit, but if I put the breakpoint at

await t;

the program just hangs, it never gets to await t;


--- Code: --- internal async Task<Boolean> SendOutputReportViaInterruptTransfer
(FileStream fileStreamDeviceData, SafeFileHandle hidHandle, Byte[] outputReportBuffer, CancellationTokenSource cts)
{
try
{
var success = false;

// Begin writing the Output report.

Task t = fileStreamDeviceData.WriteAsync(outputReportBuffer, 0, outputReportBuffer.Length, cts.Token);

await t;

// Gets to here only if the write operation completed before a timeout.

Debug.Print("Asynchronous write completed");

// The operation has one of these completion states:

switch (t.Status)
{
case TaskStatus.RanToCompletion:
success = true;
Debug.Print("Output report written to device");
break;
case TaskStatus.Canceled:
Debug.Print("Task canceled");
break;
case TaskStatus.Faulted:
Debug.Print("Unhandled exception");
break;
}

return success;
}
catch (Exception ex)
{
DisplayException(ModuleName, ex);
throw;
}
}
--- End code ---

Victor M:
Okay, just to clarify - when there is a pending request for an IN report, and an OUT report is requested, the OUT report will be blocked until the IN report has completed, then the OUT report will complete.

Is there a way to cancel the IN report request, so the OUT report can be sent without waiting?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version