Commit f36e9e3a authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

winebus.sys: Report the native product string for some Xbox gamepads.

Some games are checking the hid product string of connected gamepads in order to decide whether or not to activate rumble. Wine usually delegates these queries to the backend driver, but they don't always report the same product strings as on Windows. This will allow to override backend strings with the actual strings as reported by native drivers. Signed-off-by: 's avatarRémi Bernon <rbernon@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 3d2f43a1
......@@ -49,22 +49,39 @@ WINE_DECLARE_DEBUG_CHANNEL(hid_report);
static const WCHAR backslashW[] = {'\\',0};
struct product_desc
{
WORD vid;
WORD pid;
const WCHAR* manufacturer;
const WCHAR* product;
const WCHAR* serialnumber;
};
#define VID_MICROSOFT 0x045e
static const WORD PID_XBOX_CONTROLLERS[] = {
0x0202, /* Xbox Controller */
0x0285, /* Xbox Controller S */
0x0289, /* Xbox Controller S */
0x028e, /* Xbox360 Controller */
0x028f, /* Xbox360 Wireless Controller */
0x02d1, /* Xbox One Controller */
0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */
0x02e0, /* Xbox One X Controller */
0x02e3, /* Xbox One Elite Controller */
0x02e6, /* Wireless XBox Controller Dongle */
0x02ea, /* Xbox One S Controller */
0x02fd, /* Xbox One S Controller (Firmware 2017) */
0x0719, /* Xbox 360 Wireless Adapter */
static const WCHAR xbox360_product_string[] = {
'C','o','n','t','r','o','l','l','e','r',' ','(','X','B','O','X',' ','3','6','0',' ','F','o','r',' ','W','i','n','d','o','w','s',')',0
};
static const WCHAR xboxone_product_string[] = {
'C','o','n','t','r','o','l','l','e','r',' ','(','X','B','O','X',' ','O','n','e',' ','F','o','r',' ','W','i','n','d','o','w','s',')',0
};
static const struct product_desc XBOX_CONTROLLERS[] = {
{VID_MICROSOFT, 0x0202, NULL, NULL, NULL}, /* Xbox Controller */
{VID_MICROSOFT, 0x0285, NULL, NULL, NULL}, /* Xbox Controller S */
{VID_MICROSOFT, 0x0289, NULL, NULL, NULL}, /* Xbox Controller S */
{VID_MICROSOFT, 0x028e, NULL, xbox360_product_string, NULL}, /* Xbox360 Controller */
{VID_MICROSOFT, 0x028f, NULL, xbox360_product_string, NULL}, /* Xbox360 Wireless Controller */
{VID_MICROSOFT, 0x02d1, NULL, xboxone_product_string, NULL}, /* Xbox One Controller */
{VID_MICROSOFT, 0x02dd, NULL, xboxone_product_string, NULL}, /* Xbox One Controller (Covert Forces/Firmware 2015) */
{VID_MICROSOFT, 0x02e0, NULL, NULL, NULL}, /* Xbox One X Controller */
{VID_MICROSOFT, 0x02e3, NULL, xboxone_product_string, NULL}, /* Xbox One Elite Controller */
{VID_MICROSOFT, 0x02e6, NULL, NULL, NULL}, /* Wireless XBox Controller Dongle */
{VID_MICROSOFT, 0x02ea, NULL, xboxone_product_string, NULL}, /* Xbox One S Controller */
{VID_MICROSOFT, 0x02fd, NULL, xboxone_product_string, NULL}, /* Xbox One S Controller (Firmware 2017) */
{VID_MICROSOFT, 0x0719, NULL, xbox360_product_string, NULL}, /* Xbox 360 Wireless Adapter */
};
static DRIVER_OBJECT *driver_obj;
......@@ -518,6 +535,55 @@ static NTSTATUS deliver_last_report(struct device_extension *ext, DWORD buffer_l
}
}
static NTSTATUS hid_get_native_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length)
{
struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
const struct product_desc *vendor_products;
unsigned int i, vendor_products_size = 0;
if (ext->vid == VID_MICROSOFT)
{
vendor_products = XBOX_CONTROLLERS;
vendor_products_size = ARRAY_SIZE(XBOX_CONTROLLERS);
}
for (i = 0; i < vendor_products_size; i++)
{
if (ext->pid == vendor_products[i].pid)
break;
}
if (i >= vendor_products_size)
return STATUS_UNSUCCESSFUL;
switch (index)
{
case HID_STRING_ID_IPRODUCT:
if (vendor_products[i].product)
{
strcpyW(buffer, vendor_products[i].product);
return STATUS_SUCCESS;
}
break;
case HID_STRING_ID_IMANUFACTURER:
if (vendor_products[i].manufacturer)
{
strcpyW(buffer, vendor_products[i].manufacturer);
return STATUS_SUCCESS;
}
break;
case HID_STRING_ID_ISERIALNUMBER:
if (vendor_products[i].serialnumber)
{
strcpyW(buffer, vendor_products[i].serialnumber);
return STATUS_SUCCESS;
}
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
{
NTSTATUS status = irp->IoStatus.u.Status;
......@@ -597,6 +663,8 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
DWORD index = (ULONG_PTR)irpsp->Parameters.DeviceIoControl.Type3InputBuffer;
TRACE("IOCTL_HID_GET_STRING[%08x]\n", index);
irp->IoStatus.u.Status = status = hid_get_native_string(device, index, (WCHAR *)irp->UserBuffer, length);
if (status != STATUS_SUCCESS)
irp->IoStatus.u.Status = status = ext->vtbl->get_string(device, index, (WCHAR *)irp->UserBuffer, length);
if (status == STATUS_SUCCESS)
irp->IoStatus.Information = (strlenW((WCHAR *)irp->UserBuffer) + 1) * sizeof(WCHAR);
......@@ -762,8 +830,8 @@ BOOL is_xbox_gamepad(WORD vid, WORD pid)
if (vid != VID_MICROSOFT)
return FALSE;
for (i = 0; i < ARRAY_SIZE(PID_XBOX_CONTROLLERS); i++)
if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE;
for (i = 0; i < ARRAY_SIZE(XBOX_CONTROLLERS); i++)
if (pid == XBOX_CONTROLLERS[i].pid) return TRUE;
return FALSE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment