From: Tuomas Räsänen tuomas.rasanen@opinsys.fi
device_desc.has_hid_input_relative is TRUE if the device has HID subsystem ancestor AND the HID ancestor has input subsystem descendant.
A simplified example subsystem hierarchy view for a standard USB HID input device:
USB +--> HID +--> hidraw hidraw0 | +--> input input0
In this case, device_desc.has_hid_input_relative = TRUE for hidraw0.
A simplified example subsystem hierarchy view for a non-input USB HID device (e.g. USB HID Thermometer):
USB +--> HID +--> hidraw hidraw0
In this case, device_desc.has_hid_input_relative = FALSE for hidraw0. --- dlls/winebus.sys/bus_udev.c | 52 +++++++++++++++++++++++++++++++++++++ dlls/winebus.sys/unixlib.h | 5 ++-- 2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index f8c6ccb9060..fc1a5133423 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1284,6 +1284,54 @@ static void hidraw_set_quirks(struct hidraw_device *impl, DWORD bus_type, WORD v impl->quirks |= QUIRK_DUALSENSE_BT; }
+#ifdef HAS_PROPER_INPUT_HEADER +static BOOL has_hid_input_relative(struct udev_device *dev) +{ + struct udev_device *hid_parent; + struct udev_enumerate *enumerate; + BOOL retval = FALSE; + + hid_parent = udev_device_get_parent_with_subsystem_devtype(dev, "hid", NULL); + if (!hid_parent) + { + TRACE("Device '%s' does not have 'hid' subsystem parent.\n", udev_device_get_syspath(hid_parent)); + return FALSE; + } + + enumerate = udev_enumerate_new(udev_context); + if (!enumerate) + { + ERR("Failed to create udev enumeration object.\n"); + return FALSE; + } + + if (udev_enumerate_add_match_subsystem(enumerate, "input") < 0) + { + ERR("Failed to add subsystem 'input' match to enumeration.\n"); + goto out; + } + + if (udev_enumerate_add_match_parent(enumerate, hid_parent) < 0) + { + ERR("Failed to add parent '%s' match to enumeration.\n", udev_device_get_syspath(hid_parent)); + goto out; + } + + if (udev_enumerate_scan_devices(enumerate) < 0) + { + ERR("Failed to scan devices.\n"); + goto out; + } + + retval = udev_enumerate_get_list_entry(enumerate) != NULL; +out: + udev_enumerate_unref(enumerate); + enumerate = NULL; + + return retval; +} +#endif + static void udev_add_device(struct udev_device *dev, int fd) { struct device_desc desc = @@ -1313,6 +1361,10 @@ static void udev_add_device(struct udev_device *dev, int fd) get_device_subsystem_info(dev, "input", &desc, &bus); get_device_subsystem_info(dev, "usb", &desc, &bus);
+#ifdef HAS_PROPER_INPUT_HEADER + desc.has_hid_input_relative = has_hid_input_relative(dev); +#endif + subsystem = udev_device_get_subsystem(dev); if (!strcmp(subsystem, "hidraw")) { diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index 80852696dd1..c228dd88769 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -39,6 +39,7 @@ struct device_desc UINT uid; BOOL is_gamepad; BOOL is_hidraw; + BOOL has_hid_input_relative;
WCHAR manufacturer[MAX_PATH]; WCHAR product[MAX_PATH]; @@ -148,8 +149,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, is_hidraw %u}", - desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->is_gamepad, desc->is_hidraw); + return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u, is_hidraw %u, has_hid_input_relative %u}", + desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->is_gamepad, desc->is_hidraw, desc->has_hid_input_relative); }
static inline BOOL is_xbox_gamepad(WORD vid, WORD pid)