Module: wine Branch: master Commit: 9479e217b8a9d5fd71cf7b24953dd2ece786de04 URL: https://source.winehq.org/git/wine.git/?a=commit;h=9479e217b8a9d5fd71cf7b249...
Author: Rémi Bernon rbernon@codeweavers.com Date: Wed Jan 12 17:24:00 2022 +0100
hidclass.sys: Always read InputReportByteLength bytes when not polling.
This fixes several games (e.g. ICEY) not working well with DS4 gamepad over bluetooth, as we fixup the input report sizes, and the game expects them to be longer.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/dinput/tests/hid.c | 1 - dlls/hidclass.sys/device.c | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index d6232d578ca..a0fd2f6c660 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -2314,7 +2314,6 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - todo_wine_if( report_id ) ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
CloseHandle( overlapped.hEvent ); diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index dd288a82b67..0744865f8f7 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -53,15 +53,16 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) IoCompleteRequest(irp, IO_NO_INCREMENT); }
-static struct hid_report *hid_report_create( HID_XFER_PACKET *packet ) +static struct hid_report *hid_report_create( HID_XFER_PACKET *packet, ULONG length ) { struct hid_report *report;
- if (!(report = malloc( offsetof( struct hid_report, buffer[packet->reportBufferLen] ) ))) + if (!(report = malloc( offsetof( struct hid_report, buffer[length] ) ))) return NULL; report->ref = 1; - report->length = packet->reportBufferLen; - memcpy( report->buffer, packet->reportBuffer, report->length ); + report->length = length; + memcpy( report->buffer, packet->reportBuffer, packet->reportBufferLen ); + memset( report->buffer + packet->reportBufferLen, 0, length - packet->reportBufferLen );
return report; } @@ -218,18 +219,19 @@ static struct hid_report *hid_queue_pop_report( struct hid_queue *queue ) static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *packet ) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; const BOOL polled = ext->u.pdo.information.Polled; + ULONG size, report_len = polled ? packet->reportBufferLen : desc->InputLength; struct hid_report *last_report, *report; struct hid_queue *queue; LIST_ENTRY completed, *entry; RAWINPUT *rawinput; - ULONG size; KIRQL irql; IRP *irp;
if (IsEqualGUID( ext->class_guid, &GUID_DEVINTERFACE_HID )) { - size = offsetof( RAWINPUT, data.hid.bRawData[packet->reportBufferLen] ); + size = offsetof( RAWINPUT, data.hid.bRawData[report_len] ); if (!(rawinput = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); else { @@ -240,8 +242,9 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack rawinput->header.hDevice = ULongToHandle( ext->u.pdo.rawinput_handle ); rawinput->header.wParam = RIM_INPUT; rawinput->data.hid.dwCount = 1; - rawinput->data.hid.dwSizeHid = packet->reportBufferLen; + rawinput->data.hid.dwSizeHid = report_len; memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen ); + memset( rawinput->data.hid.bRawData + packet->reportBufferLen, 0, report_len - packet->reportBufferLen );
input.type = INPUT_HARDWARE; input.hi.uMsg = WM_INPUT; @@ -253,7 +256,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack } }
- if (!(last_report = hid_report_create( packet ))) + if (!(last_report = hid_report_create( packet, report_len ))) { ERR( "Failed to allocate hid_report!\n" ); return;