winebus: Allow specific devices to prefer hidraw backend.
And use SDL otherwise in priority over evdev for abstracted HID device implementation.
This commit is contained in:
parent
ef31616393
commit
814d2c176d
4 changed files with 57 additions and 42 deletions
|
@ -271,7 +271,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
|
||||||
{
|
{
|
||||||
struct device_desc desc =
|
struct device_desc desc =
|
||||||
{
|
{
|
||||||
.input = -1,
|
.input = -1, .is_hidraw = TRUE,
|
||||||
.serialnumber = {'0','0','0','0',0},
|
.serialnumber = {'0','0','0','0',0},
|
||||||
};
|
};
|
||||||
struct iohid_device *impl;
|
struct iohid_device *impl;
|
||||||
|
|
|
@ -530,29 +530,6 @@ static const struct raw_device_vtbl hidraw_device_vtbl =
|
||||||
|
|
||||||
#ifdef HAS_PROPER_INPUT_HEADER
|
#ifdef HAS_PROPER_INPUT_HEADER
|
||||||
|
|
||||||
static const char *get_device_syspath(struct udev_device *dev)
|
|
||||||
{
|
|
||||||
struct udev_device *parent;
|
|
||||||
|
|
||||||
if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, "hid", NULL)))
|
|
||||||
return udev_device_get_syspath(parent);
|
|
||||||
|
|
||||||
if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device")))
|
|
||||||
return udev_device_get_syspath(parent);
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct base_device *find_device_from_syspath(const char *path)
|
|
||||||
{
|
|
||||||
struct base_device *impl;
|
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(impl, &device_list, struct base_device, unix_device.entry)
|
|
||||||
if (!strcmp(get_device_syspath(impl->udev_device), path)) return impl;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
|
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
|
||||||
|
|
||||||
static const USAGE_AND_PAGE *what_am_I(struct udev_device *dev, int fd)
|
static const USAGE_AND_PAGE *what_am_I(struct udev_device *dev, int fd)
|
||||||
|
@ -1312,15 +1289,6 @@ static void udev_add_device(struct udev_device *dev, int fd)
|
||||||
|
|
||||||
TRACE("udev %s syspath %s\n", debugstr_a(devnode), udev_device_get_syspath(dev));
|
TRACE("udev %s syspath %s\n", debugstr_a(devnode), udev_device_get_syspath(dev));
|
||||||
|
|
||||||
#ifdef HAS_PROPER_INPUT_HEADER
|
|
||||||
if ((impl = find_device_from_syspath(get_device_syspath(dev))))
|
|
||||||
{
|
|
||||||
TRACE("duplicate device found, not adding the new one\n");
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
get_device_subsystem_info(dev, "hid", &desc, &bus);
|
get_device_subsystem_info(dev, "hid", &desc, &bus);
|
||||||
get_device_subsystem_info(dev, "input", &desc, &bus);
|
get_device_subsystem_info(dev, "input", &desc, &bus);
|
||||||
get_device_subsystem_info(dev, "usb", &desc, &bus);
|
get_device_subsystem_info(dev, "usb", &desc, &bus);
|
||||||
|
@ -1334,6 +1302,7 @@ static void udev_add_device(struct udev_device *dev, int fd)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!desc.manufacturer[0]) memcpy(desc.manufacturer, hidraw, sizeof(hidraw));
|
if (!desc.manufacturer[0]) memcpy(desc.manufacturer, hidraw, sizeof(hidraw));
|
||||||
|
desc.is_hidraw = TRUE;
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_HIDRAW_H
|
#ifdef HAVE_LINUX_HIDRAW_H
|
||||||
if (!desc.product[0] && ioctl(fd, HIDIOCGRAWNAME(sizeof(product) - 1), product) >= 0)
|
if (!desc.product[0] && ioctl(fd, HIDIOCGRAWNAME(sizeof(product) - 1), product) >= 0)
|
||||||
|
|
|
@ -401,6 +401,36 @@ static DWORD check_bus_option(const WCHAR *option, DWORD default_value)
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL is_hidraw_enabled(WORD vid, WORD pid)
|
||||||
|
{
|
||||||
|
char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[1024])];
|
||||||
|
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||||
|
WCHAR vidpid[MAX_PATH], *tmp;
|
||||||
|
BOOL prefer_hidraw = FALSE;
|
||||||
|
UNICODE_STRING str;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
if (check_bus_option(L"DisableHidraw", FALSE)) return FALSE;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&str, L"EnableHidraw");
|
||||||
|
if (!NtQueryValueKey(driver_key, &str, KeyValuePartialInformation, info,
|
||||||
|
sizeof(buffer) - sizeof(WCHAR), &size))
|
||||||
|
{
|
||||||
|
UINT len = swprintf(vidpid, ARRAY_SIZE(vidpid), L"%04X:%04X", vid, pid);
|
||||||
|
size -= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
|
||||||
|
tmp = (WCHAR *)info->Data;
|
||||||
|
|
||||||
|
while (size >= len * sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
if (!wcsnicmp(tmp, vidpid, len)) prefer_hidraw = TRUE;
|
||||||
|
size -= (len + 1) * sizeof(WCHAR);
|
||||||
|
tmp += len + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefer_hidraw;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL deliver_next_report(struct device_extension *ext, IRP *irp)
|
static BOOL deliver_next_report(struct device_extension *ext, IRP *irp)
|
||||||
{
|
{
|
||||||
struct hid_report *report;
|
struct hid_report *report;
|
||||||
|
@ -580,6 +610,14 @@ static DWORD CALLBACK bus_main_thread(void *args)
|
||||||
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||||
break;
|
break;
|
||||||
case BUS_EVENT_TYPE_DEVICE_CREATED:
|
case BUS_EVENT_TYPE_DEVICE_CREATED:
|
||||||
|
{
|
||||||
|
const struct device_desc *desc = &event->device_created.desc;
|
||||||
|
if (!desc->is_hidraw != !is_hidraw_enabled(desc->vid, desc->pid))
|
||||||
|
{
|
||||||
|
WARN("ignoring %shidraw device %04x:%04x\n", desc->is_hidraw ? "" : "non-", desc->vid, desc->pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
device = bus_create_hid_device(&event->device_created.desc, event->device);
|
device = bus_create_hid_device(&event->device_created.desc, event->device);
|
||||||
if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||||
else
|
else
|
||||||
|
@ -589,6 +627,7 @@ static DWORD CALLBACK bus_main_thread(void *args)
|
||||||
winebus_call(device_remove, ¶ms);
|
winebus_call(device_remove, ¶ms);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case BUS_EVENT_TYPE_INPUT_REPORT:
|
case BUS_EVENT_TYPE_INPUT_REPORT:
|
||||||
RtlEnterCriticalSection(&device_list_cs);
|
RtlEnterCriticalSection(&device_list_cs);
|
||||||
device = bus_find_unix_device(event->device);
|
device = bus_find_unix_device(event->device);
|
||||||
|
@ -739,7 +778,7 @@ static NTSTATUS sdl_driver_init(void)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS udev_driver_init(void)
|
static NTSTATUS udev_driver_init(BOOL enable_sdl)
|
||||||
{
|
{
|
||||||
struct udev_bus_options bus_options;
|
struct udev_bus_options bus_options;
|
||||||
struct bus_main_params bus =
|
struct bus_main_params bus =
|
||||||
|
@ -752,7 +791,7 @@ static NTSTATUS udev_driver_init(void)
|
||||||
|
|
||||||
bus_options.disable_hidraw = check_bus_option(L"DisableHidraw", 0);
|
bus_options.disable_hidraw = check_bus_option(L"DisableHidraw", 0);
|
||||||
if (bus_options.disable_hidraw) TRACE("UDEV hidraw devices disabled in registry\n");
|
if (bus_options.disable_hidraw) TRACE("UDEV hidraw devices disabled in registry\n");
|
||||||
bus_options.disable_input = check_bus_option(L"DisableInput", 0);
|
bus_options.disable_input = check_bus_option(L"DisableInput", 0) || enable_sdl;
|
||||||
if (bus_options.disable_input) TRACE("UDEV input devices disabled in registry\n");
|
if (bus_options.disable_input) TRACE("UDEV input devices disabled in registry\n");
|
||||||
bus_options.disable_udevd = check_bus_option(L"DisableUdevd", 0);
|
bus_options.disable_udevd = check_bus_option(L"DisableUdevd", 0);
|
||||||
if (bus_options.disable_udevd) TRACE("UDEV udevd use disabled in registry\n");
|
if (bus_options.disable_udevd) TRACE("UDEV udevd use disabled in registry\n");
|
||||||
|
@ -771,12 +810,19 @@ static NTSTATUS iohid_driver_init(void)
|
||||||
.wait_code = iohid_wait,
|
.wait_code = iohid_wait,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (check_bus_option(L"DisableHidraw", FALSE))
|
||||||
|
{
|
||||||
|
TRACE("IOHID hidraw devices disabled in registry\n");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
return bus_main_thread_start(&bus);
|
return bus_main_thread_start(&bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
|
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
|
||||||
|
BOOL enable_sdl;
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
|
|
||||||
switch (irpsp->MinorFunction)
|
switch (irpsp->MinorFunction)
|
||||||
|
@ -788,11 +834,10 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
mouse_device_create();
|
mouse_device_create();
|
||||||
keyboard_device_create();
|
keyboard_device_create();
|
||||||
|
|
||||||
if (!check_bus_option(L"Enable SDL", 1) || sdl_driver_init())
|
if ((enable_sdl = check_bus_option(L"Enable SDL", 1)))
|
||||||
{
|
enable_sdl = !sdl_driver_init();
|
||||||
udev_driver_init();
|
udev_driver_init(enable_sdl);
|
||||||
iohid_driver_init();
|
iohid_driver_init();
|
||||||
}
|
|
||||||
|
|
||||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct device_desc
|
||||||
UINT input;
|
UINT input;
|
||||||
UINT uid;
|
UINT uid;
|
||||||
BOOL is_gamepad;
|
BOOL is_gamepad;
|
||||||
|
BOOL is_hidraw;
|
||||||
|
|
||||||
WCHAR manufacturer[MAX_PATH];
|
WCHAR manufacturer[MAX_PATH];
|
||||||
WCHAR product[MAX_PATH];
|
WCHAR product[MAX_PATH];
|
||||||
|
@ -147,8 +148,8 @@ enum unix_funcs
|
||||||
static inline const char *debugstr_device_desc(struct device_desc *desc)
|
static inline const char *debugstr_device_desc(struct device_desc *desc)
|
||||||
{
|
{
|
||||||
if (!desc) return "(null)";
|
if (!desc) return "(null)";
|
||||||
return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u}",
|
return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u, is_hidraw %u}",
|
||||||
desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->is_gamepad);
|
desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->is_gamepad, desc->is_hidraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __WINEBUS_UNIXLIB_H */
|
#endif /* __WINEBUS_UNIXLIB_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue