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;