From: Matthias Gorzellik matthias.gorzellik@gmail.com
--- dlls/winebus.sys/main.c | 43 +++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index f7a634dbfe2..fe73ec603cf 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -87,7 +87,7 @@ struct device_extension
struct hid_report *last_reports[256]; struct list reports; - IRP *pending_read; + IRP *pending_reads[256];
UINT32 report_fixups; UINT64 unix_device; @@ -252,13 +252,13 @@ static WCHAR *get_compatible_ids(DEVICE_OBJECT *device) return dst; }
-static IRP *pop_pending_read(struct device_extension *ext) +static IRP *pop_pending_read(struct device_extension *ext, ULONG report_id) { IRP *pending;
RtlEnterCriticalSection(&ext->cs); - pending = ext->pending_read; - ext->pending_read = NULL; + pending = ext->pending_reads[report_id]; + ext->pending_reads[report_id] = NULL; RtlLeaveCriticalSection(&ext->cs);
return pending; @@ -268,12 +268,16 @@ static void remove_pending_irps(DEVICE_OBJECT *device) { struct device_extension *ext = device->DeviceExtension; IRP *pending; + UINT i;
- if ((pending = pop_pending_read(ext))) + for ( i = 0; i < ARRAY_SIZE(ext->pending_reads); ++i ) { - pending->IoStatus.Status = STATUS_DELETE_PENDING; - pending->IoStatus.Information = 0; - IoCompleteRequest(pending, IO_NO_INCREMENT); + if ((pending = pop_pending_read(ext, i))) + { + pending->IoStatus.Status = STATUS_DELETE_PENDING; + pending->IoStatus.Information = 0; + IoCompleteRequest(pending, IO_NO_INCREMENT); + } } }
@@ -478,6 +482,7 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re ULONG size = offsetof(struct hid_report, buffer[report_len]); struct hid_report *report, *last_report; IRP *irp; + UINT i, j;
if (!(report = RtlAllocateHeap(GetProcessHeap(), 0, size))) return; memcpy(report->buffer, report_buf, report_len); @@ -539,11 +544,20 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re RtlEnterCriticalSection(&ext->cs); list_add_tail(&ext->reports, &report->entry);
- if (!ext->collection_desc.ReportIDs[0].ReportID) last_report = ext->last_reports[0]; - else last_report = ext->last_reports[report_buf[0]]; - memcpy(last_report->buffer, report_buf, report_len); + for ( i = 0; i < ext->collection_desc.CollectionDescLength; ++i ) + { + HIDP_COLLECTION_DESC *desc = &ext->collection_desc.CollectionDesc[i]; + for ( j = 0; j < ext->collection_desc.ReportIDsLength; ++j ) + { + if (ext->collection_desc.ReportIDs[j].CollectionNumber != desc->CollectionNumber) continue; + if (!ext->collection_desc.ReportIDs[j].ReportID) last_report = ext->last_reports[0]; + else last_report = ext->last_reports[report_buf[0]]; + memcpy(last_report->buffer, report_buf, report_len); + break; + } + }
- if ((irp = pop_pending_read(ext))) + if ((irp = pop_pending_read(ext, report_buf[0]))) { deliver_next_report(ext, irp); IoCompleteRequest(irp, IO_NO_INCREMENT); @@ -1259,9 +1273,10 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) { if (!deliver_next_report(ext, irp)) { + UCHAR reportId = ((PUCHAR)irp->UserBuffer)[0]; /* hidclass.sys should guarantee this */ - assert(!ext->pending_read); - ext->pending_read = irp; + assert(!ext->pending_reads[reportId]); + ext->pending_reads[reportId] = irp; IoMarkIrpPending(irp); irp->IoStatus.Status = STATUS_PENDING; }