From: Matthias Gorzellik <matthias.gorzellik(a)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; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6074