winebus.sys: Do not depend on USB devices.

Allows for bluetooth devices to work as well
Based on work and testing by Michael Menegakis <arxeio@gmail.com>.

Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Aric Stewart 2018-02-20 13:53:19 -06:00 committed by Alexandre Julliard
parent a40ec8fcb1
commit 164517fe57
1 changed files with 69 additions and 24 deletions

View File

@ -23,6 +23,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
@ -617,17 +618,6 @@ static inline WCHAR *strdupAtoW(const char *src)
return dst; return dst;
} }
static DWORD get_sysattr_dword(struct udev_device *dev, const char *sysattr, int base)
{
const char *attr = udev_device_get_sysattr_value(dev, sysattr);
if (!attr)
{
WARN("Could not get %s from device\n", sysattr);
return 0;
}
return strtol(attr, NULL, base);
}
static WCHAR *get_sysattr_string(struct udev_device *dev, const char *sysattr) static WCHAR *get_sysattr_string(struct udev_device *dev, const char *sysattr)
{ {
const char *attr = udev_device_get_sysattr_value(dev, sysattr); const char *attr = udev_device_get_sysattr_value(dev, sysattr);
@ -680,23 +670,23 @@ static NTSTATUS hidraw_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer,
static NTSTATUS hidraw_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) static NTSTATUS hidraw_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length)
{ {
struct udev_device *usbdev; struct udev_device *hiddev;
struct platform_private *private = impl_from_DEVICE_OBJECT(device); struct platform_private *private = impl_from_DEVICE_OBJECT(device);
WCHAR *str = NULL; WCHAR *str = NULL;
usbdev = udev_device_get_parent_with_subsystem_devtype(private->udev_device, "usb", "usb_device"); hiddev = udev_device_get_parent_with_subsystem_devtype(private->udev_device, "hid", NULL);
if (usbdev) if (hiddev)
{ {
switch (index) switch (index)
{ {
case HID_STRING_ID_IPRODUCT: case HID_STRING_ID_IPRODUCT:
str = get_sysattr_string(usbdev, "product"); str = get_sysattr_string(hiddev, "product");
break; break;
case HID_STRING_ID_IMANUFACTURER: case HID_STRING_ID_IMANUFACTURER:
str = get_sysattr_string(usbdev, "manufacturer"); str = get_sysattr_string(hiddev, "manufacturer");
break; break;
case HID_STRING_ID_ISERIALNUMBER: case HID_STRING_ID_ISERIALNUMBER:
str = get_sysattr_string(usbdev, "serial"); str = get_sysattr_string(hiddev, "serial");
break; break;
default: default:
ERR("Unhandled string index %08x\n", index); ERR("Unhandled string index %08x\n", index);
@ -1049,16 +1039,71 @@ static int check_same_device(DEVICE_OBJECT *device, void* context)
return !compare_platform_device(device, context); return !compare_platform_device(device, context);
} }
static int parse_uevent_info(const char *uevent, DWORD *vendor_id,
DWORD *product_id, WCHAR **serial_number)
{
DWORD bus_type;
char *tmp = strdup(uevent);
char *saveptr = NULL;
char *line;
char *key;
char *value;
int found_id = 0;
int found_serial = 0;
line = strtok_r(tmp, "\n", &saveptr);
while (line != NULL)
{
/* line: "KEY=value" */
key = line;
value = strchr(line, '=');
if (!value)
{
goto next_line;
}
*value = '\0';
value++;
if (strcmp(key, "HID_ID") == 0)
{
/**
* type vendor product
* HID_ID=0003:000005AC:00008242
**/
int ret = sscanf(value, "%x:%x:%x", &bus_type, vendor_id, product_id);
if (ret == 3)
found_id = 1;
}
else if (strcmp(key, "HID_UNIQ") == 0)
{
/* The caller has to free the serial number */
if (strlen(value))
{
*serial_number = (WCHAR*)strdupAtoW(value);
found_serial = 1;
}
}
next_line:
line = strtok_r(NULL, "\n", &saveptr);
}
free(tmp);
return (found_id && found_serial);
}
static void try_add_device(struct udev_device *dev) static void try_add_device(struct udev_device *dev)
{ {
DWORD vid = 0, pid = 0, version = 0; DWORD vid = 0, pid = 0, version = 0;
struct udev_device *usbdev = NULL; struct udev_device *hiddev = NULL;
DEVICE_OBJECT *device = NULL; DEVICE_OBJECT *device = NULL;
const char *subsystem; const char *subsystem;
const char *devnode; const char *devnode;
WCHAR *serial = NULL; WCHAR *serial = NULL;
BOOL is_gamepad = FALSE; BOOL is_gamepad = FALSE;
int fd; int fd;
static const CHAR *base_serial = "0000";
if (!(devnode = udev_device_get_devnode(dev))) if (!(devnode = udev_device_get_devnode(dev)))
return; return;
@ -1070,8 +1115,8 @@ static void try_add_device(struct udev_device *dev)
} }
subsystem = udev_device_get_subsystem(dev); subsystem = udev_device_get_subsystem(dev);
usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); hiddev = udev_device_get_parent_with_subsystem_devtype(dev, "hid", NULL);
if (usbdev) if (hiddev)
{ {
#ifdef HAS_PROPER_INPUT_HEADER #ifdef HAS_PROPER_INPUT_HEADER
const platform_vtbl *other_vtbl = NULL; const platform_vtbl *other_vtbl = NULL;
@ -1090,10 +1135,10 @@ static void try_add_device(struct udev_device *dev)
return; return;
} }
#endif #endif
vid = get_sysattr_dword(usbdev, "idVendor", 16); parse_uevent_info(udev_device_get_sysattr_value(hiddev, "uevent"),
pid = get_sysattr_dword(usbdev, "idProduct", 16); &vid, &pid, &serial);
version = get_sysattr_dword(usbdev, "version", 10); if (serial == NULL)
serial = get_sysattr_string(usbdev, "serial"); serial = strdupAtoW(base_serial);
} }
#ifdef HAS_PROPER_INPUT_HEADER #ifdef HAS_PROPER_INPUT_HEADER
else else