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 =
|
||||
{
|
||||
.input = -1,
|
||||
.input = -1, .is_hidraw = TRUE,
|
||||
.serialnumber = {'0','0','0','0',0},
|
||||
};
|
||||
struct iohid_device *impl;
|
||||
|
|
|
@ -530,29 +530,6 @@ static const struct raw_device_vtbl hidraw_device_vtbl =
|
|||
|
||||
#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)))
|
||||
|
||||
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));
|
||||
|
||||
#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, "input", &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
|
||||
|
||||
if (!desc.manufacturer[0]) memcpy(desc.manufacturer, hidraw, sizeof(hidraw));
|
||||
desc.is_hidraw = TRUE;
|
||||
|
||||
#ifdef HAVE_LINUX_HIDRAW_H
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct hid_report *report;
|
||||
|
@ -580,6 +610,14 @@ static DWORD CALLBACK bus_main_thread(void *args)
|
|||
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||
break;
|
||||
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);
|
||||
if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
||||
else
|
||||
|
@ -589,6 +627,7 @@ static DWORD CALLBACK bus_main_thread(void *args)
|
|||
winebus_call(device_remove, ¶ms);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BUS_EVENT_TYPE_INPUT_REPORT:
|
||||
RtlEnterCriticalSection(&device_list_cs);
|
||||
device = bus_find_unix_device(event->device);
|
||||
|
@ -739,7 +778,7 @@ static NTSTATUS sdl_driver_init(void)
|
|||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS udev_driver_init(void)
|
||||
static NTSTATUS udev_driver_init(BOOL enable_sdl)
|
||||
{
|
||||
struct udev_bus_options bus_options;
|
||||
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);
|
||||
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");
|
||||
bus_options.disable_udevd = check_bus_option(L"DisableUdevd", 0);
|
||||
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,
|
||||
};
|
||||
|
||||
if (check_bus_option(L"DisableHidraw", FALSE))
|
||||
{
|
||||
TRACE("IOHID hidraw devices disabled in registry\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return bus_main_thread_start(&bus);
|
||||
}
|
||||
|
||||
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||
{
|
||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
|
||||
BOOL enable_sdl;
|
||||
NTSTATUS ret;
|
||||
|
||||
switch (irpsp->MinorFunction)
|
||||
|
@ -788,11 +834,10 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
|||
mouse_device_create();
|
||||
keyboard_device_create();
|
||||
|
||||
if (!check_bus_option(L"Enable SDL", 1) || sdl_driver_init())
|
||||
{
|
||||
udev_driver_init();
|
||||
iohid_driver_init();
|
||||
}
|
||||
if ((enable_sdl = check_bus_option(L"Enable SDL", 1)))
|
||||
enable_sdl = !sdl_driver_init();
|
||||
udev_driver_init(enable_sdl);
|
||||
iohid_driver_init();
|
||||
|
||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
|
|
@ -38,6 +38,7 @@ struct device_desc
|
|||
UINT input;
|
||||
UINT uid;
|
||||
BOOL is_gamepad;
|
||||
BOOL is_hidraw;
|
||||
|
||||
WCHAR manufacturer[MAX_PATH];
|
||||
WCHAR product[MAX_PATH];
|
||||
|
@ -147,8 +148,8 @@ enum unix_funcs
|
|||
static inline const char *debugstr_device_desc(struct device_desc *desc)
|
||||
{
|
||||
if (!desc) return "(null)";
|
||||
return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u}",
|
||||
desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->is_gamepad);
|
||||
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->is_hidraw);
|
||||
}
|
||||
|
||||
#endif /* __WINEBUS_UNIXLIB_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue