winebus.sys: Correctly set HID device input number in device endpoint path.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2019-05-15 14:56:05 +02:00 committed by Alexandre Julliard
parent 6a0005747c
commit 8cd6d61639
5 changed files with 42 additions and 19 deletions

View File

@ -43,7 +43,7 @@ void *get_platform_private(DEVICE_OBJECT *device) DECLSPEC_HIDDEN;
/* HID Plug and Play Bus */
NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW, WORD vid, WORD pid,
DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
WORD input, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
const GUID *class, const platform_vtbl *vtbl, DWORD platform_data_size) DECLSPEC_HIDDEN;
DEVICE_OBJECT *bus_find_hid_device(const platform_vtbl *vtbl, void *platform_dev) DECLSPEC_HIDDEN;
void bus_remove_hid_device(DEVICE_OBJECT *device) DECLSPEC_HIDDEN;

View File

@ -345,7 +345,8 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
}
}
device = bus_create_hid_device(iohid_driver_obj, busidW, vid, pid, version, uid, str?serial_string:NULL, is_gamepad, &GUID_DEVCLASS_IOHID, &iohid_vtbl, sizeof(struct platform_private));
device = bus_create_hid_device(iohid_driver_obj, busidW, vid, pid, -1, version, uid, str?serial_string:NULL,
is_gamepad, &GUID_DEVCLASS_IOHID, &iohid_vtbl, sizeof(struct platform_private));
if (!device)
ERR("Failed to create device\n");
else

View File

@ -941,7 +941,8 @@ static void try_add_device(SDL_JoystickID index)
is_xbox_gamepad = (axis_count == 6 && button_count >= 14);
}
device = bus_create_hid_device(sdl_driver_obj, sdl_busidW, vid, pid, version, id, serial, is_xbox_gamepad, &GUID_DEVCLASS_SDL, &sdl_vtbl, sizeof(struct platform_private));
device = bus_create_hid_device(sdl_driver_obj, sdl_busidW, vid, pid, -1, version, id, serial,
is_xbox_gamepad, &GUID_DEVCLASS_SDL, &sdl_vtbl, sizeof(struct platform_private));
if (device)
{

View File

@ -1064,7 +1064,7 @@ static int check_same_device(DEVICE_OBJECT *device, void* context)
}
static int parse_uevent_info(const char *uevent, DWORD *vendor_id,
DWORD *product_id, WCHAR **serial_number)
DWORD *product_id, WORD *input, WCHAR **serial_number)
{
DWORD bus_type;
char *tmp;
@ -1110,6 +1110,12 @@ static int parse_uevent_info(const char *uevent, DWORD *vendor_id,
found_serial = 1;
}
}
else if (strcmp(key, "HID_PHYS") == 0)
{
const char *input_no = strstr(value, "input");
if (input_no)
*input = atoi(input_no+5 );
}
next_line:
line = strtok_r(NULL, "\n", &saveptr);
@ -1128,6 +1134,7 @@ static void try_add_device(struct udev_device *dev)
const char *devnode;
WCHAR *serial = NULL;
BOOL is_gamepad = FALSE;
WORD input = -1;
int fd;
static const CHAR *base_serial = "0000";
@ -1162,7 +1169,7 @@ static void try_add_device(struct udev_device *dev)
}
#endif
parse_uevent_info(udev_device_get_sysattr_value(hiddev, "uevent"),
&vid, &pid, &serial);
&vid, &pid, &input, &serial);
if (serial == NULL)
serial = strdupAtoW(base_serial);
}
@ -1205,13 +1212,13 @@ static void try_add_device(struct udev_device *dev)
if (strcmp(subsystem, "hidraw") == 0)
{
device = bus_create_hid_device(udev_driver_obj, hidraw_busidW, vid, pid, version, 0, serial, is_gamepad,
device = bus_create_hid_device(udev_driver_obj, hidraw_busidW, vid, pid, input, version, 0, serial, is_gamepad,
&GUID_DEVCLASS_HIDRAW, &hidraw_vtbl, sizeof(struct platform_private));
}
#ifdef HAS_PROPER_INPUT_HEADER
else if (strcmp(subsystem, "input") == 0)
{
device = bus_create_hid_device(udev_driver_obj, lnxev_busidW, vid, pid, version, 0, serial, is_gamepad,
device = bus_create_hid_device(udev_driver_obj, lnxev_busidW, vid, pid, input, version, 0, serial, is_gamepad,
&GUID_DEVCLASS_LINUXEVENT, &lnxev_vtbl, sizeof(struct wine_input_private));
}
#endif

View File

@ -71,7 +71,7 @@ struct device_extension
{
struct pnp_device *pnp_device;
WORD vid, pid;
WORD vid, pid, input;
DWORD uid, version, index;
BOOL is_gamepad;
WCHAR *serial;
@ -119,15 +119,15 @@ void *get_platform_private(DEVICE_OBJECT *device)
return ext->platform_private;
}
static DWORD get_vidpid_index(WORD vid, WORD pid)
static DWORD get_device_index(WORD vid, WORD pid, WORD input)
{
struct pnp_device *ptr;
DWORD index = 1;
DWORD index = 0;
LIST_FOR_EACH_ENTRY(ptr, &pnp_devset, struct pnp_device, entry)
{
struct device_extension *ext = (struct device_extension *)ptr->device->DeviceExtension;
if (ext->vid == vid && ext->pid == pid)
if (ext->vid == vid && ext->pid == pid && ext->input == input)
index = max(ext->index + 1, index);
}
@ -136,16 +136,28 @@ static DWORD get_vidpid_index(WORD vid, WORD pid)
static WCHAR *get_instance_id(DEVICE_OBJECT *device)
{
static const WCHAR formatW[] = {'%','s','\\','V','i','d','_','%','0','4','x','&', 'P','i','d','_','%','0','4','x','&',
'%','s','_','%','i','\\','%','i','&','%','s','&','%','x',0};
static const WCHAR formatW[] = {'%','s','\\','v','i','d','_','%','0','4','x','&','p','i','d','_','%','0','4','x',
'\\','%','i','&','%','s','&','%','x','&','%','i',0};
static const WCHAR format_inputW[] = {'%','s','\\','v','i','d','_','%','0','4','x','&','p','i','d','_','%','0','4','x','&',
'%','s','_','%','i','\\','%','i','&','%','s','&','%','x','&','%','i',0};
struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
const WCHAR *serial = ext->serial ? ext->serial : zero_serialW;
DWORD len = strlenW(ext->busid) + strlenW(serial) + 64;
WCHAR *dst;
if ((dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
sprintfW(dst, formatW, ext->busid, ext->vid, ext->pid, ext->is_gamepad ? igW : miW,
ext->index, ext->version, serial, ext->uid);
{
if (ext->input == (WORD)-1)
{
sprintfW(dst, formatW, ext->busid, ext->vid, ext->pid,
ext->version, serial, ext->uid, ext->index);
}
else
{
sprintfW(dst, format_inputW, ext->busid, ext->vid, ext->pid, ext->is_gamepad ? igW : miW,
ext->input, ext->version, serial, ext->uid, ext->index);
}
}
return dst;
}
@ -197,7 +209,7 @@ static WCHAR *get_compatible_ids(DEVICE_OBJECT *device)
}
DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW, WORD vid, WORD pid,
DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
WORD input, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
const GUID *class, const platform_vtbl *vtbl, DWORD platform_data_size)
{
static const WCHAR device_name_fmtW[] = {'\\','D','e','v','i','c','e','\\','%','s','#','%','p',0};
@ -212,8 +224,9 @@ DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW,
NTSTATUS status;
DWORD length;
TRACE("(%p, %s, %04x, %04x, %u, %u, %s, %u, %s, %p, %u)\n", driver, debugstr_w(busidW), vid, pid,
version, uid, debugstr_w(serialW), is_gamepad, debugstr_guid(class), vtbl, platform_data_size);
TRACE("(%p, %s, %04x, %04x, %04x, %u, %u, %s, %u, %s, %p, %u)\n", driver,
debugstr_w(busidW), vid, pid, input, version, uid, debugstr_w(serialW),
is_gamepad, debugstr_guid(class), vtbl, platform_data_size);
if (!(pnp_dev = HeapAlloc(GetProcessHeap(), 0, sizeof(*pnp_dev))))
return NULL;
@ -236,9 +249,10 @@ DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW,
ext->pnp_device = pnp_dev;
ext->vid = vid;
ext->pid = pid;
ext->input = input;
ext->uid = uid;
ext->version = version;
ext->index = get_vidpid_index(vid, pid);
ext->index = get_device_index(vid, pid, input);
ext->is_gamepad = is_gamepad;
ext->serial = strdupW(serialW);
ext->busid = busidW;