hidclass.sys: Move product string overrides from winexinput.sys.
Some games expect the DS4 gamepads to be named like native drivers, and they aren't detected xinput-compatible when access through hidraw, so it's not possible to override their product string in winexinput.sys. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
db3e592270
commit
60ef452922
|
@ -404,14 +404,62 @@ static void handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR( IRP *irp, BASE_DEVICE_EX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct device_strings
|
||||||
|
{
|
||||||
|
const WCHAR *id;
|
||||||
|
const WCHAR *product;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct device_strings device_strings[] =
|
||||||
|
{
|
||||||
|
{ .id = L"VID_045E&PID_028E", .product = L"Controller (XBOX 360 For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_028F", .product = L"Controller (XBOX 360 For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_02D1", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_02DD", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_02E3", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_02EA", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_02FD", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_0719", .product = L"Controller (XBOX 360 For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_0B00", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_0B05", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_0B12", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
{ .id = L"VID_045E&PID_0B13", .product = L"Controller (Xbox One For Windows)" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const WCHAR *find_product_string( const WCHAR *device_id )
|
||||||
|
{
|
||||||
|
const WCHAR *match_id = wcsrchr( device_id, '\\' ) + 1;
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(device_strings); ++i)
|
||||||
|
if (!wcsnicmp( device_strings[i].id, match_id, 17 ))
|
||||||
|
return device_strings[i].product;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_minidriver_string( BASE_DEVICE_EXTENSION *ext, IRP *irp, ULONG index )
|
static void handle_minidriver_string( BASE_DEVICE_EXTENSION *ext, IRP *irp, ULONG index )
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||||
WCHAR *output_buf = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
|
WCHAR *output_buf = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
|
||||||
ULONG output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
ULONG output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
const WCHAR *str = NULL;
|
||||||
|
|
||||||
call_minidriver( IOCTL_HID_GET_STRING, ext->u.pdo.parent_fdo, ULongToPtr( index ),
|
if (index == HID_STRING_ID_IPRODUCT) str = find_product_string( ext->device_id );
|
||||||
sizeof(index), output_buf, output_len, &irp->IoStatus );
|
|
||||||
|
if (!str) call_minidriver( IOCTL_HID_GET_STRING, ext->u.pdo.parent_fdo, ULongToPtr( index ),
|
||||||
|
sizeof(index), output_buf, output_len, &irp->IoStatus );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
irp->IoStatus.Information = (wcslen( str ) + 1) * sizeof(WCHAR);
|
||||||
|
if (irp->IoStatus.Information > output_len)
|
||||||
|
irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy( output_buf, str, irp->IoStatus.Information );
|
||||||
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP *irp )
|
static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP *irp )
|
||||||
|
|
|
@ -315,80 +315,17 @@ static NTSTATUS try_complete_pending_read(DEVICE_OBJECT *device, IRP *irp)
|
||||||
return IoCallDriver(fdo->bus_device, xinput_irp);
|
return IoCallDriver(fdo->bus_device, xinput_irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct device_strings
|
|
||||||
{
|
|
||||||
const WCHAR *id;
|
|
||||||
const WCHAR *product;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct device_strings device_strings[] =
|
|
||||||
{
|
|
||||||
{ .id = L"VID_045E&PID_028E", .product = L"Controller (XBOX 360 For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_028F", .product = L"Controller (XBOX 360 For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_02D1", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_02DD", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_02E3", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_02EA", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_02FD", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_0719", .product = L"Controller (XBOX 360 For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_0B00", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_0B05", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_0B12", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
{ .id = L"VID_045E&PID_0B13", .product = L"Controller (Xbox One For Windows)" },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const WCHAR *find_product_string(const WCHAR *device_id)
|
|
||||||
{
|
|
||||||
const WCHAR *match_id = wcsrchr(device_id, '\\') + 1;
|
|
||||||
DWORD i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(device_strings); ++i)
|
|
||||||
if (!wcsnicmp(device_strings[i].id, match_id, 17))
|
|
||||||
return device_strings[i].product;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS WINAPI gamepad_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
static NTSTATUS WINAPI gamepad_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
|
||||||
ULONG output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
ULONG output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
|
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
|
||||||
struct func_device *fdo = fdo_from_DEVICE_OBJECT(device);
|
struct func_device *fdo = fdo_from_DEVICE_OBJECT(device);
|
||||||
struct device *impl = impl_from_DEVICE_OBJECT(device);
|
|
||||||
const WCHAR *str = NULL;
|
|
||||||
|
|
||||||
TRACE("device %p, irp %p, code %#x, bus_device %p.\n", device, irp, code, fdo->bus_device);
|
TRACE("device %p, irp %p, code %#x, bus_device %p.\n", device, irp, code, fdo->bus_device);
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case IOCTL_HID_GET_STRING:
|
|
||||||
switch ((ULONG_PTR)stack->Parameters.DeviceIoControl.Type3InputBuffer)
|
|
||||||
{
|
|
||||||
case HID_STRING_ID_IPRODUCT:
|
|
||||||
str = find_product_string(impl->device_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
{
|
|
||||||
IoSkipCurrentIrpStackLocation(irp);
|
|
||||||
return IoCallDriver(fdo->bus_device, irp);
|
|
||||||
}
|
|
||||||
|
|
||||||
irp->IoStatus.Information = (wcslen(str) + 1) * sizeof(WCHAR);
|
|
||||||
if (output_len < irp->IoStatus.Information)
|
|
||||||
{
|
|
||||||
irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wcscpy(irp->UserBuffer, str);
|
|
||||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
|
||||||
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
|
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
|
||||||
{
|
{
|
||||||
HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer;
|
HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer;
|
||||||
|
|
Loading…
Reference in New Issue