From: Rémi Bernon rbernon@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,
From: Rémi Bernon rbernon@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 ); }
From: Matthias Gorzellik matthias.gorzellik@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; }
From: Rémi Bernon rbernon@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;
From: Rémi Bernon rbernon@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 );
From: Rémi Bernon rbernon@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;
From: Matthias Gorzellik matthias.gorzellik@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; }
From: Matthias Gorzellik matthias.gorzellik@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;
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.