From: Connor McAdams cmcadams@codeweavers.com
Some games use the bus device instance to query properties of a HID device. Tekken 8 does this to get a string for the device to display in the UI. It queries all present devices for their container IDs, and when it finds one with the same container ID as the HID device, it checks the device instance string for a "BTHENUM" or "USB" enumerator.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/winebus.sys/bus_iohid.c | 9 +++++++-- dlls/winebus.sys/bus_udev.c | 3 ++- dlls/winebus.sys/main.c | 22 ++++++++++++++++------ dlls/winebus.sys/unixlib.h | 14 +++++++++++--- 4 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index 648d55dadb8..0b9a0c52c46 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -287,8 +287,13 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void * desc.uid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDLocationIDKey)));
if ((str = IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDTransportKey)))) - desc.is_bluetooth = !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothValue), 0) || - !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothLowEnergyValue), 0); + { + if (!CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothValue), 0) || + !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothLowEnergyValue), 0)) + desc.bus_type = BUS_TYPE_BLUETOOTH; + else if (!CFStringCompare(str, CFSTR(kIOHIDTransportUSBValue), 0)) + desc.bus_type = BUS_TYPE_USB; + }
if (usages.UsagePage != HID_USAGE_PAGE_GENERIC || !(usages.Usage == HID_USAGE_GENERIC_JOYSTICK || usages.Usage == HID_USAGE_GENERIC_GAMEPAD)) diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 4f929d0cb45..fec7a74f989 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1362,7 +1362,8 @@ static void udev_add_device(struct udev_device *dev, int fd) get_device_subsystem_info(dev, "hid", NULL, &desc, &bus); get_device_subsystem_info(dev, "input", NULL, &desc, &bus); get_device_subsystem_info(dev, "usb", "usb_device", &desc, &bus); - if (bus == BUS_BLUETOOTH) desc.is_bluetooth = TRUE; + if (bus == BUS_BLUETOOTH) desc.bus_type = BUS_TYPE_BLUETOOTH; + else if (bus == BUS_USB) desc.bus_type = BUS_TYPE_USB;
if (!(subsystem = udev_device_get_subsystem(dev))) { diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 49b805b713e..d839f451809 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -203,21 +203,31 @@ static WCHAR *get_instance_id(DEVICE_OBJECT *device) return dst; }
+static const WCHAR *bus_type_str[] = +{ + L"WINEBUS", /* BUS_TYPE_UNKNOWN */ + L"USB", /* BUS_TYPE_USB */ + L"BTHENUM", /* BUS_TYPE_BLUETOOTH */ +}; + static WCHAR *get_device_id(DEVICE_OBJECT *device) { static const WCHAR input_format[] = L"&MI_%02u"; - static const WCHAR winebus_format[] = L"WINEBUS\VID_%04X&PID_%04X"; + static const WCHAR winebus_format[] = L"%s\VID_%04X&PID_%04X"; struct device_extension *ext = (struct device_extension *)device->DeviceExtension; - DWORD pos = 0, len = 0, input_len = 0, winebus_len = 25; + DWORD pos = 0, len = 0, input_len = 0, winebus_len = 18; + const WCHAR *bus_str; WCHAR *dst;
+ assert(ext->desc.bus_type < BUS_TYPE_COUNT); + bus_str = bus_type_str[ext->desc.bus_type]; if (ext->desc.input != -1) input_len = 14;
- len += winebus_len + input_len + 1; + len += winebus_len + input_len + wcslen(bus_str) + 1;
if ((dst = ExAllocatePool(PagedPool, len * sizeof(WCHAR)))) { - pos += swprintf(dst + pos, len - pos, winebus_format, ext->desc.vid, ext->desc.pid); + pos += swprintf(dst + pos, len - pos, winebus_format, bus_str, ext->desc.vid, ext->desc.pid); if (input_len) pos += swprintf(dst + pos, len - pos, input_format, ext->desc.input); }
@@ -367,12 +377,12 @@ static DEVICE_OBJECT *bus_create_hid_device(struct device_desc *desc, UINT64 uni ext->unix_device = unix_device; list_init(&ext->reports);
- if (desc->is_hidraw && desc->is_bluetooth && is_dualshock4_gamepad(desc->vid, desc->pid)) + if (desc->is_hidraw && (desc->bus_type == BUS_TYPE_BLUETOOTH) && is_dualshock4_gamepad(desc->vid, desc->pid)) { TRACE("Enabling report fixup for Bluetooth DualShock4 device %p\n", device); ext->report_fixups |= HIDRAW_FIXUP_DUALSHOCK_BT; } - if (desc->is_hidraw && desc->is_bluetooth && is_dualsense_gamepad(desc->vid, desc->pid)) + if (desc->is_hidraw && (desc->bus_type == BUS_TYPE_BLUETOOTH) && is_dualsense_gamepad(desc->vid, desc->pid)) { TRACE("Enabling report fixup for Bluetooth DualSense device %p\n", device); ext->report_fixups |= HIDRAW_FIXUP_DUALSENSE_BT; diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index f8626438c92..b296f20178d 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -38,9 +38,9 @@ struct device_desc UINT version; UINT input; UINT uid; + UINT bus_type; BOOL is_gamepad; BOOL is_hidraw; - BOOL is_bluetooth;
WCHAR manufacturer[MAX_PATH]; WCHAR product[MAX_PATH]; @@ -78,6 +78,14 @@ enum bus_event_type BUS_EVENT_TYPE_INPUT_REPORT, };
+enum bus_type +{ + BUS_TYPE_UNKNOWN, + BUS_TYPE_USB, + BUS_TYPE_BLUETOOTH, + BUS_TYPE_COUNT, +}; + struct bus_event { UINT type; @@ -153,9 +161,9 @@ 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, is_bluetooth %u}", + return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u, is_hidraw %u, bus_type %u}", desc->vid, desc->pid, desc->version, desc->input, desc->uid, - desc->is_gamepad, desc->is_hidraw, desc->is_bluetooth); + desc->is_gamepad, desc->is_hidraw, desc->bus_type); }
static inline BOOL is_xbox_gamepad(WORD vid, WORD pid)