[PATCH v3] winebus.sys: Handle device reports for hidraw devices
Aric Stewart
aric at codeweavers.com
Wed Oct 19 14:32:10 CDT 2016
Hi,
It is important to remember that there is a big difference between the user level communications with the HID device and the minidriver level communications. The top of the stack, the HID device, has a ring buffer and such.
On 10/19/16 12:32 PM, Sebastian Lackner wrote:
> On 19.10.2016 10:50, Aric Stewart wrote:
>>
>> I dont think that is a big problem. Not that it wont happen but that
>> it is ok to have happen. The 2 ways to read from the
>> minidriver/device layer is to either get the last report from the
>> device or current device state (IOCTL_HID_GET_INPUT_REPORT) or to
>> wait for the next report from the device(IOCTL_HID_READ_REPORT).
>>
>> There is not specification of a need for a ring buffer or anything
>> like that in the MSDN docs that I can see so it seem like keeping it
>> simple and direct is the best.
>
> Even if missing a report is not a problem, doesn't it cause an arbitrary
> long delay when we have to wait for the next report? I have not been able
> to find much information about buffering in HID drivers, but at least
> some drivers seem to implement that. For example:
>
Depends on the call that is made. IOCTL_HID_GET_INPUT_REPORT should always return immediately, if there is no report then it returns 0. If there is a report it returns the last report from the device.
IOCTL_HID_READ_REPORT is expected to pend until a report is available. In the grand scheme of things IOCTL_HID_READ_REPORT is expected to block until a report is available because the general use is that hidclass will be in a loop where it does a IOCTL_HID_READ_REPORT call and when the call succeeds it places that report into the ring buffer and then immediately calls again to get the next report.
IOCTL_HID_GET_INPUT_REPORT is generated by the corresponding IOCTL_HID_GET_INPUT_REPORT in the class driver and HidD_GetInputReport.
IOCTL_HID_READ_REPORT is like doing a FileRead.
So they need to behave quite a bit differently.
> https://www.julianloehr.de/wp-content/uploads/2014/07/Paper_HIDWiimote.pdf
> """In case the Wiimote state changes when there is no read request
> currently buffered, a flag is used to signal whether a newly received
> read request shall be processed and completed immediately."""
>
That would not be hard, just a flag that showed if the last reports has been read or not. In all practical terms the minidriver only has 1 consumer, the hidclass class driver devices, so in many ways the whole IRP queue is overkill as there should only ever be 1 client. It would not be hard to add that.
> In Wine we have to cache the last report anyway, so we could implement
> something similar very easy. Do you think it makes sense? The
> implementation of IOCTL_HID_GET_INPUT_REPORT and IOCTL_HID_READ_REPORT
> would also not be much more difficult, as shown in the following
> pseudocode:
>
> --- snip ---
> case IOCTL_HID_GET_INPUT_REPORT:
> case IOCTL_HID_READ_REPORT:
> EnterCriticalSection(report_cs);
> ... start processing if not done yet ...
> if (ioctl == IOCTL_HID_READ_REPORT && (!last_report || last_report_seen))
> {
> ... async handling ...
> break;
> }
> ... synchronous handlng ...
> last_report_seen = TRUE;
> LeaveCriticalSection(report_cs);
> break;
> --- snip ---
I will have to explore this when I have more time to code things but the basic idea looks pretty good though IOCTL_HID_GET_INPUT_REPORT uses HID_XFER_PACKETs and IOCTL_HID_READ_REPORT does not so that complicates things a fair bit more.
-aric
More information about the wine-devel
mailing list