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 ---
v2: Fix length in the hid_report allocation.
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;