[PATCH 0/8] MR6206: hidclass: Implement multiple TLC support.
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/dinput/tests/hid.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 4dc3a60cdff..c33a1c25086 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -4035,8 +4035,27 @@ static void test_hid_multiple_tlc(void) .usage_page = 0x01, }, }; + struct hid_expect input[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_len = desc.caps.InputReportByteLength, + .report_buf = {1,0x01,0x02,0x03,0x04,0x05,0x06}, + .ret_length = 6, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_READ_REPORT, + .report_len = desc.caps.InputReportByteLength, + .report_buf = {2,0x11,0x12,0x13,0x14,0x15,0x16}, + .ret_length = 6, + .ret_status = STATUS_SUCCESS, + }, + }; WCHAR device_path[MAX_PATH]; + char report[16]; + ULONG value; HANDLE file; BOOL ret; @@ -4058,6 +4077,17 @@ static void test_hid_multiple_tlc(void) ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); check_preparsed_data( file, &expect_kdr_joystick, ARRAY_SIZE(expect_caps_joystick), expect_caps_joystick, ARRAY_SIZE(expect_nodes_joystick), expect_nodes_joystick ); + + send_hid_input( file, input, sizeof(input) ); + + memset( report, 0xcd, sizeof(report) ); + SetLastError( 0xdeadbeef ); + ret = ReadFile( file, report, desc.caps.InputReportByteLength, &value, NULL ); + ok( ret, "ReadFile failed, last error %lu\n", GetLastError() ); + ok( value == 6, "ReadFile returned %lx\n", value ); + ok( report[0] == 1, "unexpected report data\n" ); + ok( report[1] == 0x01, "unexpected report data\n" ); + CloseHandle( file ); swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col02", desc.attributes.VendorID, @@ -4070,6 +4100,17 @@ static void test_hid_multiple_tlc(void) ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); check_preparsed_data( file, &expect_kdr_gamepad, ARRAY_SIZE(expect_caps_gamepad), expect_caps_gamepad, ARRAY_SIZE(expect_nodes_gamepad), expect_nodes_gamepad ); + + send_hid_input( file, input, sizeof(input) ); + + memset( report, 0xcd, sizeof(report) ); + SetLastError( 0xdeadbeef ); + ret = ReadFile( file, report, desc.caps.InputReportByteLength, &value, NULL ); + ok( ret, "ReadFile failed, last error %lu\n", GetLastError() ); + ok( value == 6, "ReadFile returned %lx\n", value ); + ok( report[0] == 2, "unexpected report data\n" ); + ok( report[1] == 0x11, "unexpected report data\n" ); + CloseHandle( file ); swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col03", desc.attributes.VendorID, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/hidparse.sys/main.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index feb5b3531a4..46cd47423cd 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -656,15 +656,10 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de memset( device_desc, 0, sizeof(*device_desc) ); - if (!(preparsed = parse_descriptor( report_desc, report_desc_len, pool_type ))) - return HIDP_STATUS_INTERNAL_ERROR; - - if (!(device_desc->CollectionDesc = ExAllocatePool( pool_type, sizeof(*device_desc->CollectionDesc) ))) - { - free( preparsed ); - return STATUS_NO_MEMORY; - } + len = sizeof(*device_desc->CollectionDesc); + if (!(device_desc->CollectionDesc = ExAllocatePool( pool_type, len ))) goto failed; + if (!(preparsed = parse_descriptor( report_desc, report_desc_len, pool_type ))) goto failed; len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); @@ -705,12 +700,8 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de feature_len[caps->report_id] = max(feature_len[caps->report_id], len); } - if (!(device_desc->ReportIDs = ExAllocatePool( pool_type, sizeof(*device_desc->ReportIDs) * report_count ))) - { - free( preparsed ); - ExFreePool( device_desc->CollectionDesc ); - return STATUS_NO_MEMORY; - } + len = sizeof(*device_desc->ReportIDs) * report_count; + if (!(device_desc->ReportIDs = ExAllocatePool( pool_type, len ))) goto failed; for (i = 0, report_count = 0; i < 256; ++i) { @@ -725,12 +716,25 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de device_desc->ReportIDsLength = report_count; return HIDP_STATUS_SUCCESS; + +failed: + if (device_desc->CollectionDesc) + { + for (i = 0; i < device_desc->CollectionDescLength; ++i) + ExFreePool( device_desc->CollectionDesc[i].PreparsedData ); + ExFreePool( device_desc->CollectionDesc ); + } + return HIDP_STATUS_INTERNAL_ERROR; } void WINAPI HidP_FreeCollectionDescription( HIDP_DEVICE_DESC *device_desc ) { + UINT i; + TRACE( "device_desc %p.\n", device_desc ); + for (i = 0; i < device_desc->CollectionDescLength; ++i) + ExFreePool( device_desc->CollectionDesc[i].PreparsedData ); ExFreePool( device_desc->CollectionDesc ); ExFreePool( device_desc->ReportIDs ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Matthias Gorzellik <matthias.gorzellik(a)gmail.com> --- dlls/hidparse.sys/main.c | 136 ++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 46cd47423cd..8a497e53227 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -644,60 +644,116 @@ done: return data; } +static BYTE **parse_top_level_collections( BYTE *descriptor, unsigned int length, ULONG *count ) +{ + BYTE *ptr, *end, **tmp, **tlcs; + UINT32 size, depth = 0; + + if (!(tlcs = malloc( sizeof(*tlcs) ))) return NULL; + tlcs[0] = descriptor; + *count = 0; + + for (ptr = descriptor, end = descriptor + length; ptr != end; ptr += size + 1) + { + size = (*ptr & 0x03); + if (size == 3) size = 4; + if (ptr + size > end) + { + ERR( "Need %d bytes to read item value\n", size ); + break; + } + +#define SHORT_ITEM( tag, type ) (((tag) << 4) | ((type) << 2)) + switch (*ptr & SHORT_ITEM( 0xf, 0x3 )) + { + case SHORT_ITEM( TAG_MAIN_COLLECTION, TAG_TYPE_MAIN ): + if (depth++) break; + break; + case SHORT_ITEM( TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN ): + if (--depth) break; + *count = *count + 1; + if (!(tmp = realloc( tlcs, (*count + 1) * sizeof(*tlcs) ))) + { + ERR( "Failed to allocate memory for TLCs\n" ); + return tlcs; + } + tlcs = tmp; + tlcs[*count] = ptr + size + 1; + break; + } +#undef SHORT_ITEM + } + + TRACE( "Found %lu TLCs\n", *count ); + return tlcs; +} + NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_desc, ULONG report_desc_len, POOL_TYPE pool_type, HIDP_DEVICE_DESC *device_desc ) { - ULONG i, len, report_count = 0, input_len[256] = {0}, output_len[256] = {0}, feature_len[256] = {0}; + ULONG i, len, tlc_count, report_count = 0, input_len[256] = {0}, output_len[256] = {0}, feature_len[256] = {0}, collection[256] = {0}; struct hid_value_caps *caps, *caps_end; struct hid_preparsed_data *preparsed; + BYTE **tlcs; TRACE( "report_desc %p, report_desc_len %lu, pool_type %u, device_desc %p.\n", report_desc, report_desc_len, pool_type, device_desc ); memset( device_desc, 0, sizeof(*device_desc) ); - len = sizeof(*device_desc->CollectionDesc); + if (!(tlcs = parse_top_level_collections( report_desc, report_desc_len, &tlc_count ))) goto failed; + + len = sizeof(*device_desc->CollectionDesc) * tlc_count; if (!(device_desc->CollectionDesc = ExAllocatePool( pool_type, len ))) goto failed; - if (!(preparsed = parse_descriptor( report_desc, report_desc_len, pool_type ))) goto failed; - len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + - preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); - - device_desc->CollectionDescLength = 1; - device_desc->CollectionDesc[0].UsagePage = preparsed->usage_page; - device_desc->CollectionDesc[0].Usage = preparsed->usage; - device_desc->CollectionDesc[0].CollectionNumber = 1; - device_desc->CollectionDesc[0].InputLength = preparsed->input_report_byte_length; - device_desc->CollectionDesc[0].OutputLength = preparsed->output_report_byte_length; - device_desc->CollectionDesc[0].FeatureLength = preparsed->feature_report_byte_length; - device_desc->CollectionDesc[0].PreparsedDataLength = len; - device_desc->CollectionDesc[0].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed; - - caps = HID_INPUT_VALUE_CAPS( preparsed ); - caps_end = caps + preparsed->input_caps_end - preparsed->input_caps_start; - for (; caps != caps_end; ++caps) + for (i = 0; i < tlc_count; ++i) { - len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; - if (!input_len[caps->report_id]) report_count++; - input_len[caps->report_id] = max(input_len[caps->report_id], len); - } + TRACE( "parsing TLC %lu, start %p, end %p\n", i, tlcs[i], tlcs[i + 1] ); + + if (!(preparsed = parse_descriptor( tlcs[i], tlcs[i + 1] - tlcs[i], pool_type ))) goto failed; + + len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); + + device_desc->CollectionDescLength++; + device_desc->CollectionDesc[i].UsagePage = preparsed->usage_page; + device_desc->CollectionDesc[i].Usage = preparsed->usage; + device_desc->CollectionDesc[i].CollectionNumber = i + 1; + device_desc->CollectionDesc[i].InputLength = preparsed->input_report_byte_length; + device_desc->CollectionDesc[i].OutputLength = preparsed->output_report_byte_length; + device_desc->CollectionDesc[i].FeatureLength = preparsed->feature_report_byte_length; + device_desc->CollectionDesc[i].PreparsedDataLength = len; + device_desc->CollectionDesc[i].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed; + + caps = HID_INPUT_VALUE_CAPS( preparsed ); + caps_end = caps + preparsed->input_caps_end - preparsed->input_caps_start; + for (; caps != caps_end; ++caps) + { + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; + if (!input_len[caps->report_id]) report_count++; + input_len[caps->report_id] = max(input_len[caps->report_id], len); + collection[caps->report_id] = i; + } - caps = HID_OUTPUT_VALUE_CAPS( preparsed ); - caps_end = caps + preparsed->output_caps_end - preparsed->output_caps_start; - for (; caps != caps_end; ++caps) - { - len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; - if (!input_len[caps->report_id] && !output_len[caps->report_id]) report_count++; - output_len[caps->report_id] = max(output_len[caps->report_id], len); - } + caps = HID_OUTPUT_VALUE_CAPS( preparsed ); + caps_end = caps + preparsed->output_caps_end - preparsed->output_caps_start; + for (; caps != caps_end; ++caps) + { + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; + if (!input_len[caps->report_id] && !output_len[caps->report_id]) report_count++; + output_len[caps->report_id] = max(output_len[caps->report_id], len); + collection[caps->report_id] = i; + } - caps = HID_FEATURE_VALUE_CAPS( preparsed ); - caps_end = caps + preparsed->feature_caps_end - preparsed->feature_caps_start; - for (; caps != caps_end; ++caps) - { - len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; - if (!input_len[caps->report_id] && !output_len[caps->report_id] && !feature_len[caps->report_id]) report_count++; - feature_len[caps->report_id] = max(feature_len[caps->report_id], len); + caps = HID_FEATURE_VALUE_CAPS( preparsed ); + caps_end = caps + preparsed->feature_caps_end - preparsed->feature_caps_start; + for (; caps != caps_end; ++caps) + { + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; + if (!input_len[caps->report_id] && !output_len[caps->report_id] && !feature_len[caps->report_id]) report_count++; + feature_len[caps->report_id] = max(feature_len[caps->report_id], len); + collection[caps->report_id] = i; + } } len = sizeof(*device_desc->ReportIDs) * report_count; @@ -707,7 +763,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de { if (!input_len[i] && !output_len[i] && !feature_len[i]) continue; device_desc->ReportIDs[report_count].ReportID = i; - device_desc->ReportIDs[report_count].CollectionNumber = 1; + device_desc->ReportIDs[report_count].CollectionNumber = collection[i] + 1; device_desc->ReportIDs[report_count].InputLength = (input_len[i] + 7) / 8; device_desc->ReportIDs[report_count].OutputLength = (output_len[i] + 7) / 8; device_desc->ReportIDs[report_count].FeatureLength = (feature_len[i] + 7) / 8; @@ -715,6 +771,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de } device_desc->ReportIDsLength = report_count; + free( tlcs ); return HIDP_STATUS_SUCCESS; failed: @@ -724,6 +781,7 @@ failed: ExFreePool( device_desc->CollectionDesc[i].PreparsedData ); ExFreePool( device_desc->CollectionDesc ); } + free( tlcs ); return HIDP_STATUS_INTERNAL_ERROR; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/hidclass.sys/device.c | 13 ++-- dlls/hidclass.sys/hid.h | 5 +- dlls/hidclass.sys/pnp.c | 153 +++++++++++++++++-------------------- 3 files changed, 82 insertions(+), 89 deletions(-) diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index e6b34077a77..7c0154fda7a 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -219,7 +219,7 @@ 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; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; const BOOL polled = ext->u.pdo.information.Polled; ULONG size, report_len = polled ? packet->reportBufferLen : desc->InputLength; struct hid_report *last_report, *report; @@ -297,8 +297,9 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack static HIDP_REPORT_IDS *find_report_with_type_and_id( BASE_DEVICE_EXTENSION *ext, BYTE type, BYTE id, BOOL any_id ) { - HIDP_REPORT_IDS *report, *reports = ext->u.pdo.device_desc.ReportIDs; - ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength; + BASE_DEVICE_EXTENSION *fdo_ext = ext->u.pdo.parent_fdo->DeviceExtension; + HIDP_REPORT_IDS *report, *reports = fdo_ext->u.fdo.device_desc.ReportIDs; + ULONG report_count = fdo_ext->u.fdo.device_desc.ReportIDsLength; for (report = reports; report != reports + report_count; report++) { @@ -315,7 +316,7 @@ static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; BOOL polled = ext->u.pdo.information.Polled; HIDP_REPORT_IDS *report; HID_XFER_PACKET *packet; @@ -618,7 +619,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) } case IOCTL_HID_GET_COLLECTION_DESCRIPTOR: { - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; irp->IoStatus.Information = desc->PreparsedDataLength; if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < desc->PreparsedDataLength) @@ -694,7 +695,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) { struct hid_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); struct hid_report *report; BOOL removed; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 7b5d5f19298..25a121b2ed1 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -48,6 +48,9 @@ typedef struct _BASE_DEVICE_EXTENSION /* this must be the first member */ HID_DEVICE_EXTENSION hid_ext; + HID_DEVICE_ATTRIBUTES attrs; + HIDP_DEVICE_DESC device_desc; + DEVICE_OBJECT *child_pdo; } fdo; @@ -55,8 +58,8 @@ typedef struct _BASE_DEVICE_EXTENSION { DEVICE_OBJECT *parent_fdo; + HIDP_COLLECTION_DESC *collection_desc; HID_COLLECTION_INFORMATION information; - HIDP_DEVICE_DESC device_desc; ULONG poll_interval; HANDLE halt_event; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index ddccffb91e2..549c3489aa3 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -113,7 +113,7 @@ C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]) < sizeof(RAWIN static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param) { - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; INPUT input = {.type = INPUT_HARDWARE}; struct hid_packet hid = {0}; @@ -189,34 +189,70 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b return STATUS_SUCCESS; } -static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) +static NTSTATUS get_hid_device_desc( minidriver *minidriver, DEVICE_OBJECT *device, HIDP_DEVICE_DESC *desc ) { - BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext; - HID_DEVICE_ATTRIBUTES attr = {0}; HID_DESCRIPTOR descriptor = {0}; - HIDP_COLLECTION_DESC *desc; - DEVICE_OBJECT *child_pdo; - BYTE *reportDescriptor; - UNICODE_STRING string; - WCHAR pdo_name[255]; IO_STATUS_BLOCK io; - USAGE page, usage; - NTSTATUS status; + BYTE *report_desc; INT i; - call_minidriver( IOCTL_HID_GET_DEVICE_ATTRIBUTES, fdo, NULL, 0, &attr, sizeof(attr), &io ); + call_minidriver( IOCTL_HID_GET_DEVICE_DESCRIPTOR, device, NULL, 0, &descriptor, sizeof(descriptor), &io ); + if (io.Status) return io.Status; + + for (i = 0; i < descriptor.bNumDescriptors; i++) + if (descriptor.DescriptorList[i].bReportType == HID_REPORT_DESCRIPTOR_TYPE) + break; + if (i >= descriptor.bNumDescriptors) return STATUS_NOT_FOUND; + + if (!(report_desc = malloc( descriptor.DescriptorList[i].wReportLength ))) return STATUS_NO_MEMORY; + call_minidriver( IOCTL_HID_GET_REPORT_DESCRIPTOR, device, NULL, 0, report_desc, + descriptor.DescriptorList[i].wReportLength, &io ); + if (!io.Status) io.Status = HidP_GetCollectionDescription( report_desc, descriptor.DescriptorList[i].wReportLength, + PagedPool, desc ); + free( report_desc ); + + if (io.Status && io.Status != HIDP_STATUS_SUCCESS) return STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; +} + +static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device ) +{ + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + IO_STATUS_BLOCK io; + NTSTATUS status; + + call_minidriver( IOCTL_HID_GET_DEVICE_ATTRIBUTES, device, NULL, 0, &ext->u.fdo.attrs, + sizeof(ext->u.fdo.attrs), &io ); if (io.Status != STATUS_SUCCESS) { ERR( "Minidriver failed to get attributes, status %#lx.\n", io.Status ); - return; + return io.Status; + } + + if ((status = get_hid_device_desc( minidriver, device, &ext->u.fdo.device_desc ))) + { + ERR( "Failed to get HID device description, status %#lx\n", status ); + return status; } + return STATUS_SUCCESS; +} + +static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) +{ + BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext; + DEVICE_OBJECT *child_pdo; + UNICODE_STRING string; + WCHAR pdo_name[255]; + USAGE page, usage; + NTSTATUS status; + swprintf(pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", fdo->DriverObject, fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject); RtlInitUnicodeString(&string, pdo_name); if ((status = IoCreateDevice(fdo->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo))) { - ERR( "Failed to create child PDO, status %#lx.\n", io.Status ); + ERR( "Failed to create child PDO, status %#lx.\n", status ); return; } fdo_ext->u.fdo.child_pdo = child_pdo; @@ -225,60 +261,22 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) pdo_ext->u.pdo.parent_fdo = fdo; list_init( &pdo_ext->u.pdo.queues ); KeInitializeSpinLock( &pdo_ext->u.pdo.queues_lock ); + + pdo_ext->u.pdo.collection_desc = fdo_ext->u.fdo.device_desc.CollectionDesc; + wcscpy(pdo_ext->device_id, fdo_ext->device_id); wcscpy(pdo_ext->instance_id, fdo_ext->instance_id); wcscpy(pdo_ext->container_id, fdo_ext->container_id); pdo_ext->class_guid = fdo_ext->class_guid; - pdo_ext->u.pdo.information.VendorID = attr.VendorID; - pdo_ext->u.pdo.information.ProductID = attr.ProductID; - pdo_ext->u.pdo.information.VersionNumber = attr.VersionNumber; + pdo_ext->u.pdo.information.VendorID = fdo_ext->u.fdo.attrs.VendorID; + pdo_ext->u.pdo.information.ProductID = fdo_ext->u.fdo.attrs.ProductID; + pdo_ext->u.pdo.information.VersionNumber = fdo_ext->u.fdo.attrs.VersionNumber; pdo_ext->u.pdo.information.Polled = minidriver->minidriver.DevicesArePolled; + pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.collection_desc->PreparsedDataLength; - call_minidriver( IOCTL_HID_GET_DEVICE_DESCRIPTOR, fdo, NULL, 0, &descriptor, sizeof(descriptor), &io ); - if (io.Status != STATUS_SUCCESS) - { - ERR( "Cannot get Device Descriptor, status %#lx\n", status ); - IoDeleteDevice(child_pdo); - return; - } - for (i = 0; i < descriptor.bNumDescriptors; i++) - if (descriptor.DescriptorList[i].bReportType == HID_REPORT_DESCRIPTOR_TYPE) - break; - - if (i >= descriptor.bNumDescriptors) - { - ERR("No Report Descriptor found in reply\n"); - IoDeleteDevice(child_pdo); - return; - } - - reportDescriptor = malloc(descriptor.DescriptorList[i].wReportLength); - call_minidriver( IOCTL_HID_GET_REPORT_DESCRIPTOR, fdo, NULL, 0, reportDescriptor, - descriptor.DescriptorList[i].wReportLength, &io ); - if (io.Status != STATUS_SUCCESS) - { - ERR( "Cannot get Report Descriptor, status %#lx\n", status ); - free(reportDescriptor); - IoDeleteDevice(child_pdo); - return; - } - - io.Status = HidP_GetCollectionDescription( reportDescriptor, descriptor.DescriptorList[i].wReportLength, - PagedPool, &pdo_ext->u.pdo.device_desc ); - free(reportDescriptor); - if (io.Status != HIDP_STATUS_SUCCESS) - { - ERR("Cannot parse Report Descriptor\n"); - IoDeleteDevice(child_pdo); - return; - } - - desc = pdo_ext->u.pdo.device_desc.CollectionDesc; - pdo_ext->u.pdo.information.DescriptorSize = desc->PreparsedDataLength; - - page = desc->UsagePage; - usage = desc->Usage; + page = pdo_ext->u.pdo.collection_desc->UsagePage; + usage = pdo_ext->u.pdo.collection_desc->Usage; if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE) pdo_ext->u.pdo.rawinput_handle = WINE_MOUSE_HANDLE; else if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD) @@ -302,6 +300,7 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) minidriver *minidriver = find_minidriver(device->DriverObject); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + NTSTATUS status; TRACE("irp %p, minor function %#x.\n", irp, stack->MinorFunction); @@ -340,25 +339,17 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) } case IRP_MN_START_DEVICE: - { - NTSTATUS ret; - - if ((ret = minidriver->PNPDispatch(device, irp))) - return ret; - create_child(minidriver, device); - return STATUS_SUCCESS; - } + status = minidriver->PNPDispatch( device, irp ); + if (!status) status = initialize_device( minidriver, device ); + if (!status) create_child( minidriver, device ); + return status; case IRP_MN_REMOVE_DEVICE: - { - NTSTATUS ret; - - ret = minidriver->PNPDispatch(device, irp); - - IoDetachDevice(ext->u.fdo.hid_ext.NextDeviceObject); - IoDeleteDevice(device); - return ret; - } + status = minidriver->PNPDispatch( device, irp ); + HidP_FreeCollectionDescription( &ext->u.fdo.device_desc ); + IoDetachDevice( ext->u.fdo.hid_ext.NextDeviceObject ); + IoDeleteDevice( device ); + return status; default: return minidriver->PNPDispatch(device, irp); @@ -373,7 +364,7 @@ static WCHAR *query_hardware_ids(DEVICE_OBJECT *device) static const WCHAR hid_format[] = L"HID_DEVICE"; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; HID_COLLECTION_INFORMATION *info = &ext->u.pdo.information; WCHAR *dst; DWORD size; @@ -443,7 +434,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; NTSTATUS status = irp->IoStatus.Status; struct hid_queue *queue, *next; KIRQL irql; @@ -551,8 +542,6 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) hid_queue_destroy( queue ); KeReleaseSpinLock( &ext->u.pdo.queues_lock, irql ); - HidP_FreeCollectionDescription(&ext->u.pdo.device_desc); - RtlFreeUnicodeString(&ext->u.pdo.link_name); irp->IoStatus.Status = STATUS_SUCCESS; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/hidclass.sys/pnp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 549c3489aa3..205667b8280 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -283,14 +283,9 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) pdo_ext->u.pdo.rawinput_handle = WINE_KEYBOARD_HANDLE; else pdo_ext->u.pdo.rawinput_handle = alloc_rawinput_handle(); - - IoInvalidateDeviceRelations(fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations); - pdo_ext->u.pdo.poll_interval = DEFAULT_POLL_INTERVAL; - HID_StartDeviceThread(child_pdo); - - send_wm_input_device_change(pdo_ext, GIDC_ARRIVAL); + IoInvalidateDeviceRelations( fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations ); TRACE( "created device %p, rawinput handle %#x\n", pdo_ext, pdo_ext->u.pdo.rawinput_handle ); } @@ -493,6 +488,9 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) } case IRP_MN_START_DEVICE: + HID_StartDeviceThread(device); + send_wm_input_device_change(ext, GIDC_ARRIVAL); + if ((status = IoRegisterDeviceInterface(device, ext->class_guid, NULL, &ext->u.pdo.link_name))) { ERR( "Failed to register interface, status %#lx.\n", status ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/hidclass.sys/hid.h | 3 ++- dlls/hidclass.sys/pnp.c | 47 +++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 25a121b2ed1..5959160b273 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -51,7 +51,8 @@ typedef struct _BASE_DEVICE_EXTENSION HID_DEVICE_ATTRIBUTES attrs; HIDP_DEVICE_DESC device_desc; - DEVICE_OBJECT *child_pdo; + DEVICE_OBJECT **child_pdos; + UINT child_count; } fdo; struct diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 205667b8280..f07ed0f70ef 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -235,30 +235,37 @@ static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device return status; } + if (!(ext->u.fdo.child_pdos = malloc( ext->u.fdo.device_desc.CollectionDescLength * sizeof(ext->u.fdo.child_pdos) ))) + { + ERR( "Cannot allocate child PDOs array\n" ); + return STATUS_NO_MEMORY; + } + return STATUS_SUCCESS; } -static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) +static NTSTATUS create_child_pdos( minidriver *minidriver, DEVICE_OBJECT *device ) { - BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext; + BASE_DEVICE_EXTENSION *fdo_ext = device->DeviceExtension, *pdo_ext; DEVICE_OBJECT *child_pdo; UNICODE_STRING string; WCHAR pdo_name[255]; USAGE page, usage; NTSTATUS status; - swprintf(pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", fdo->DriverObject, - fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject); + swprintf( pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", device->DriverObject, + fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject ); RtlInitUnicodeString(&string, pdo_name); - if ((status = IoCreateDevice(fdo->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo))) + if ((status = IoCreateDevice( device->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo ))) { ERR( "Failed to create child PDO, status %#lx.\n", status ); - return; + return status; } - fdo_ext->u.fdo.child_pdo = child_pdo; + fdo_ext->u.fdo.child_pdos[0] = child_pdo; + fdo_ext->u.fdo.child_count++; pdo_ext = child_pdo->DeviceExtension; - pdo_ext->u.pdo.parent_fdo = fdo; + pdo_ext->u.pdo.parent_fdo = device; list_init( &pdo_ext->u.pdo.queues ); KeInitializeSpinLock( &pdo_ext->u.pdo.queues_lock ); @@ -285,9 +292,10 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) pdo_ext->u.pdo.rawinput_handle = alloc_rawinput_handle(); pdo_ext->u.pdo.poll_interval = DEFAULT_POLL_INTERVAL; - IoInvalidateDeviceRelations( fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations ); - TRACE( "created device %p, rawinput handle %#x\n", pdo_ext, pdo_ext->u.pdo.rawinput_handle ); + + IoInvalidateDeviceRelations( fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations ); + return STATUS_SUCCESS; } static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) @@ -304,27 +312,23 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) case IRP_MN_QUERY_DEVICE_RELATIONS: { DEVICE_RELATIONS *devices; - DEVICE_OBJECT *child; + UINT32 i; if (stack->Parameters.QueryDeviceRelations.Type != BusRelations) return minidriver->PNPDispatch(device, irp); - if (!(devices = ExAllocatePool(PagedPool, offsetof(DEVICE_RELATIONS, Objects[1])))) + if (!(devices = ExAllocatePool(PagedPool, offsetof(DEVICE_RELATIONS, Objects[ext->u.fdo.child_count])))) { irp->IoStatus.Status = STATUS_NO_MEMORY; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; } - if ((child = ext->u.fdo.child_pdo)) - { - devices->Objects[0] = ext->u.fdo.child_pdo; - call_fastcall_func1(ObfReferenceObject, ext->u.fdo.child_pdo); - devices->Count = 1; - } - else + for (i = 0, devices->Count = 0; i < ext->u.fdo.child_count; ++i) { - devices->Count = 0; + devices->Objects[i] = ext->u.fdo.child_pdos[i]; + call_fastcall_func1(ObfReferenceObject, ext->u.fdo.child_pdos[i]); + devices->Count++; } irp->IoStatus.Information = (ULONG_PTR)devices; @@ -336,12 +340,13 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) case IRP_MN_START_DEVICE: status = minidriver->PNPDispatch( device, irp ); if (!status) status = initialize_device( minidriver, device ); - if (!status) create_child( minidriver, device ); + if (!status) status = create_child_pdos( minidriver, device ); return status; case IRP_MN_REMOVE_DEVICE: status = minidriver->PNPDispatch( device, irp ); HidP_FreeCollectionDescription( &ext->u.fdo.device_desc ); + free( ext->u.fdo.child_pdos ); IoDetachDevice( ext->u.fdo.hid_ext.NextDeviceObject ); IoDeleteDevice( device ); return status; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Matthias Gorzellik <matthias.gorzellik(a)gmail.com> --- dlls/winebus.sys/main.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index f7a634dbfe2..bb588473312 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); + } } } @@ -543,7 +547,7 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re else last_report = ext->last_reports[report_buf[0]]; memcpy(last_report->buffer, report_buf, report_len); - 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 +1263,10 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) { if (!deliver_next_report(ext, irp)) { + BYTE *report_buf = (BYTE *)irp->UserBuffer; /* hidclass.sys should guarantee this */ - assert(!ext->pending_read); - ext->pending_read = irp; + assert(!ext->pending_reads[report_buf[0]]); + ext->pending_reads[report_buf[0]] = irp; IoMarkIrpPending(irp); irp->IoStatus.Status = STATUS_PENDING; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
From: Matthias Gorzellik <matthias.gorzellik(a)gmail.com> --- dlls/dinput/tests/hid.c | 4 -- dlls/hidclass.sys/device.c | 1 + dlls/hidclass.sys/hid.h | 1 + dlls/hidclass.sys/pnp.c | 105 +++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index c33a1c25086..5e48050738b 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -730,7 +730,6 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) for (i = 0; i < count; ++i) { ret = WaitForSingleObject( device_removed, i > 0 ? 500 : 5000 ); - todo_wine_if(i > 0) ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); } } @@ -755,7 +754,6 @@ BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout for (i = 0; i < count; ++i) { ret = WaitForSingleObject( device_added, timeout ); - todo_wine_if(i > 0) ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); } @@ -4068,9 +4066,7 @@ static void test_hid_multiple_tlc(void) swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col01", desc.attributes.VendorID, desc.attributes.ProductID ); ret = find_hid_device_path( device_path ); - todo_wine ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) ); - if (!ret) goto done; file = CreateFileW( device_path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 7c0154fda7a..bd4b61f147b 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -303,6 +303,7 @@ static HIDP_REPORT_IDS *find_report_with_type_and_id( BASE_DEVICE_EXTENSION *ext for (report = reports; report != reports + report_count; report++) { + if (ext->u.pdo.collection_desc->CollectionNumber != report->CollectionNumber) continue; if (!any_id && report->ReportID && report->ReportID != id) continue; if (type == HidP_Input && report->InputLength) return report; if (type == HidP_Output && report->OutputLength) return report; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 5959160b273..0ceddbf7751 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -50,6 +50,7 @@ typedef struct _BASE_DEVICE_EXTENSION HID_DEVICE_ATTRIBUTES attrs; HIDP_DEVICE_DESC device_desc; + WCHAR serial[256]; DEVICE_OBJECT **child_pdos; UINT child_count; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index f07ed0f70ef..fe8aa190165 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -218,6 +218,7 @@ static NTSTATUS get_hid_device_desc( minidriver *minidriver, DEVICE_OBJECT *devi static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device ) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + ULONG index = HID_STRING_ID_ISERIALNUMBER; IO_STATUS_BLOCK io; NTSTATUS status; @@ -229,6 +230,14 @@ static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device return io.Status; } + call_minidriver( IOCTL_HID_GET_STRING, device, ULongToPtr(index), sizeof(index), + &ext->u.fdo.serial, sizeof(ext->u.fdo.serial), &io ); + if (io.Status != STATUS_SUCCESS) + { + ERR( "Minidriver failed to get serial number, status %#lx.\n", io.Status ); + return io.Status; + } + if ((status = get_hid_device_desc( minidriver, device, &ext->u.fdo.device_desc ))) { ERR( "Failed to get HID device description, status %#lx\n", status ); @@ -252,47 +261,67 @@ static NTSTATUS create_child_pdos( minidriver *minidriver, DEVICE_OBJECT *device WCHAR pdo_name[255]; USAGE page, usage; NTSTATUS status; + INT i; - swprintf( pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", device->DriverObject, - fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject ); - RtlInitUnicodeString(&string, pdo_name); - if ((status = IoCreateDevice( device->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo ))) + for (i = 0; i < fdo_ext->u.fdo.device_desc.CollectionDescLength; ++i) { - ERR( "Failed to create child PDO, status %#lx.\n", status ); - return status; - } - fdo_ext->u.fdo.child_pdos[0] = child_pdo; - fdo_ext->u.fdo.child_count++; - - pdo_ext = child_pdo->DeviceExtension; - pdo_ext->u.pdo.parent_fdo = device; - list_init( &pdo_ext->u.pdo.queues ); - KeInitializeSpinLock( &pdo_ext->u.pdo.queues_lock ); - - pdo_ext->u.pdo.collection_desc = fdo_ext->u.fdo.device_desc.CollectionDesc; - - wcscpy(pdo_ext->device_id, fdo_ext->device_id); - wcscpy(pdo_ext->instance_id, fdo_ext->instance_id); - wcscpy(pdo_ext->container_id, fdo_ext->container_id); - pdo_ext->class_guid = fdo_ext->class_guid; - - pdo_ext->u.pdo.information.VendorID = fdo_ext->u.fdo.attrs.VendorID; - pdo_ext->u.pdo.information.ProductID = fdo_ext->u.fdo.attrs.ProductID; - pdo_ext->u.pdo.information.VersionNumber = fdo_ext->u.fdo.attrs.VersionNumber; - pdo_ext->u.pdo.information.Polled = minidriver->minidriver.DevicesArePolled; - pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.collection_desc->PreparsedDataLength; - - page = pdo_ext->u.pdo.collection_desc->UsagePage; - usage = pdo_ext->u.pdo.collection_desc->Usage; - if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE) - pdo_ext->u.pdo.rawinput_handle = WINE_MOUSE_HANDLE; - else if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD) - pdo_ext->u.pdo.rawinput_handle = WINE_KEYBOARD_HANDLE; - else - pdo_ext->u.pdo.rawinput_handle = alloc_rawinput_handle(); - pdo_ext->u.pdo.poll_interval = DEFAULT_POLL_INTERVAL; + if (fdo_ext->u.fdo.device_desc.CollectionDescLength > 1) + swprintf( pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p&%d", device->DriverObject, + fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, i ); + else + swprintf( pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", device->DriverObject, + fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject ); + + RtlInitUnicodeString(&string, pdo_name); + if ((status = IoCreateDevice( device->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo ))) + { + ERR( "Failed to create child PDO, status %#lx.\n", status ); + return status; + } + + fdo_ext->u.fdo.child_pdos[i] = child_pdo; + fdo_ext->u.fdo.child_count++; + + pdo_ext = child_pdo->DeviceExtension; + pdo_ext->u.pdo.parent_fdo = device; + list_init( &pdo_ext->u.pdo.queues ); + KeInitializeSpinLock( &pdo_ext->u.pdo.queues_lock ); + + pdo_ext->u.pdo.collection_desc = fdo_ext->u.fdo.device_desc.CollectionDesc + i; - TRACE( "created device %p, rawinput handle %#x\n", pdo_ext, pdo_ext->u.pdo.rawinput_handle ); + if (fdo_ext->u.fdo.device_desc.CollectionDescLength > 1) + { + swprintf( pdo_ext->device_id, ARRAY_SIZE(pdo_ext->device_id), L"%s&Col%02d", + fdo_ext->device_id, pdo_ext->u.pdo.collection_desc->CollectionNumber ); + swprintf( pdo_ext->instance_id, ARRAY_SIZE(pdo_ext->instance_id), L"%u&%s&%x&%u&%04u", + fdo_ext->u.fdo.attrs.VersionNumber, fdo_ext->u.fdo.serial, 0, 0, i ); + } + else + { + wcscpy( pdo_ext->device_id, fdo_ext->device_id ); + wcscpy( pdo_ext->instance_id, fdo_ext->instance_id ); + } + wcscpy(pdo_ext->container_id, fdo_ext->container_id); + pdo_ext->class_guid = fdo_ext->class_guid; + + pdo_ext->u.pdo.information.VendorID = fdo_ext->u.fdo.attrs.VendorID; + pdo_ext->u.pdo.information.ProductID = fdo_ext->u.fdo.attrs.ProductID; + pdo_ext->u.pdo.information.VersionNumber = fdo_ext->u.fdo.attrs.VersionNumber; + pdo_ext->u.pdo.information.Polled = minidriver->minidriver.DevicesArePolled; + pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.collection_desc->PreparsedDataLength; + + page = pdo_ext->u.pdo.collection_desc->UsagePage; + usage = pdo_ext->u.pdo.collection_desc->Usage; + if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE) + pdo_ext->u.pdo.rawinput_handle = WINE_MOUSE_HANDLE; + else if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD) + pdo_ext->u.pdo.rawinput_handle = WINE_KEYBOARD_HANDLE; + else + pdo_ext->u.pdo.rawinput_handle = alloc_rawinput_handle(); + pdo_ext->u.pdo.poll_interval = DEFAULT_POLL_INTERVAL; + + TRACE( "created device %p, rawinput handle %#x\n", pdo_ext, pdo_ext->u.pdo.rawinput_handle ); + } IoInvalidateDeviceRelations( fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations ); return STATUS_SUCCESS; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147543 Your paranoid android. === build (build log) === error: patch failed: dlls/dinput/tests/hid.c:4035 error: patch failed: dlls/hidparse.sys/main.c:656 error: patch failed: dlls/hidparse.sys/main.c:644 error: patch failed: dlls/hidclass.sys/device.c:219 error: patch failed: dlls/hidclass.sys/hid.h:48 error: patch failed: dlls/hidclass.sys/pnp.c:113 error: patch failed: dlls/hidclass.sys/pnp.c:283 error: patch failed: dlls/hidclass.sys/hid.h:51 error: patch failed: dlls/hidclass.sys/pnp.c:235 error: patch failed: dlls/hidclass.sys/hid.h:50 error: patch failed: dlls/hidclass.sys/pnp.c:218 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/dinput/tests/hid.c:4035 error: patch failed: dlls/hidparse.sys/main.c:656 error: patch failed: dlls/hidparse.sys/main.c:644 error: patch failed: dlls/hidclass.sys/device.c:219 error: patch failed: dlls/hidclass.sys/hid.h:48 error: patch failed: dlls/hidclass.sys/pnp.c:113 error: patch failed: dlls/hidclass.sys/pnp.c:283 error: patch failed: dlls/hidclass.sys/hid.h:51 error: patch failed: dlls/hidclass.sys/pnp.c:235 error: patch failed: dlls/hidclass.sys/hid.h:50 error: patch failed: dlls/hidclass.sys/pnp.c:218 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/dinput/tests/hid.c:4035 error: patch failed: dlls/hidparse.sys/main.c:656 error: patch failed: dlls/hidparse.sys/main.c:644 error: patch failed: dlls/hidclass.sys/device.c:219 error: patch failed: dlls/hidclass.sys/hid.h:48 error: patch failed: dlls/hidclass.sys/pnp.c:113 error: patch failed: dlls/hidclass.sys/pnp.c:283 error: patch failed: dlls/hidclass.sys/hid.h:51 error: patch failed: dlls/hidclass.sys/pnp.c:235 error: patch failed: dlls/hidclass.sys/hid.h:50 error: patch failed: dlls/hidclass.sys/pnp.c:218 Task: Patch failed to apply
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6206
participants (3)
-
Marvin -
Matthias Gorzellik -
Rémi Bernon