Aric Stewart : winebus.sys: Be more specific as to what we offer as IG_ enumerated devices.
Alexandre Julliard
julliard at winehq.org
Thu Feb 15 14:42:28 CST 2018
Module: wine
Branch: master
Commit: e48296c2f02081d224505c90e645985f95b30d1d
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e48296c2f02081d224505c90e645985f95b30d1d
Author: Aric Stewart <aric at codeweavers.com>
Date: Wed Feb 14 12:24:27 2018 -0600
winebus.sys: Be more specific as to what we offer as IG_ enumerated devices.
Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winebus.sys/bus.h | 1 +
dlls/winebus.sys/bus_iohid.c | 48 +++++++++++++++++++++++++--
dlls/winebus.sys/bus_udev.c | 79 +++++++++++++++++++++++++++++++++-----------
dlls/winebus.sys/main.c | 29 ++++++++++++++++
4 files changed, 135 insertions(+), 22 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h
index 34783f2..141e6d6 100644
--- a/dlls/winebus.sys/bus.h
+++ b/dlls/winebus.sys/bus.h
@@ -49,3 +49,4 @@ DEVICE_OBJECT* bus_enumerate_hid_devices(const platform_vtbl *vtbl, enum_func fu
/* General Bus Functions */
DWORD check_bus_option(UNICODE_STRING *registry_path, const UNICODE_STRING *option, DWORD default_value) DECLSPEC_HIDDEN;
+BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c
index 10635f8..501a40d 100644
--- a/dlls/winebus.sys/bus_iohid.c
+++ b/dlls/winebus.sys/bus_iohid.c
@@ -287,7 +287,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
DWORD vid, pid, version;
CFStringRef str = NULL;
WCHAR serial_string[256];
- BOOL is_gamepad;
+ BOOL is_gamepad = FALSE;
TRACE("OS/X IOHID Device Added %p\n", IOHIDDevice);
@@ -297,8 +297,50 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
str = IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDSerialNumberKey));
if (str) CFStringToWSTR(str, serial_string, sizeof(serial_string) / sizeof(WCHAR));
- is_gamepad = (IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad) ||
- IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick));
+ if (IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad) ||
+ IOHIDDeviceConformsTo(IOHIDDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))
+ {
+ if (is_xbox_gamepad(vid, pid))
+ is_gamepad = TRUE;
+ else
+ {
+ int axes=0, buttons=0;
+ CFArrayRef element_array = IOHIDDeviceCopyMatchingElements(
+ IOHIDDevice, NULL, kIOHIDOptionsTypeNone);
+
+ if (element_array) {
+ CFIndex index;
+ CFIndex count = CFArrayGetCount(element_array);
+ for (index = 0; index < count; index++)
+ {
+ IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(element_array, index);
+ if (element)
+ {
+ int type = IOHIDElementGetType(element);
+ if (type == kIOHIDElementTypeInput_Button) buttons++;
+ if (type == kIOHIDElementTypeInput_Axis) axes++;
+ if (type == kIOHIDElementTypeInput_Misc)
+ {
+ uint32_t usage = IOHIDElementGetUsage(element);
+ switch (usage)
+ {
+ case kHIDUsage_GD_X:
+ case kHIDUsage_GD_Y:
+ case kHIDUsage_GD_Z:
+ case kHIDUsage_GD_Rx:
+ case kHIDUsage_GD_Ry:
+ case kHIDUsage_GD_Rz:
+ case kHIDUsage_GD_Slider:
+ axes ++;
+ }
+ }
+ }
+ }
+ CFRelease(element_array);
+ }
+ is_gamepad = (axes == 6 && buttons >= 14);
+ }
+ }
device = bus_create_hid_device(iohid_driver_obj, busidW, vid, pid, version, 0, str?serial_string:NULL, is_gamepad, &GUID_DEVCLASS_IOHID, &iohid_vtbl, sizeof(struct platform_private));
if (!device)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index f80c5d7..18e1854 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -439,13 +439,55 @@ static void set_rel_axis_value(struct wine_input_private *ext, int code, int val
}
}
+static INT count_buttons(int device_fd, BYTE *map)
+{
+ int i;
+ int button_count = 0;
+ BYTE keybits[(KEY_MAX+7)/8];
+
+ if (ioctl(device_fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits) == -1)
+ {
+ WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno, strerror(errno));
+ return FALSE;
+ }
+
+ for (i = BTN_MISC; i < KEY_MAX; i++)
+ {
+ if (test_bit(keybits, i))
+ {
+ if (map) map[i] = button_count;
+ button_count++;
+ }
+ }
+ return button_count;
+}
+
+static INT count_abs_axis(int device_fd)
+{
+ BYTE absbits[(ABS_MAX+7)/8];
+ int abs_count = 0;
+ int i;
+
+ if (ioctl(device_fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits) == -1)
+ {
+ WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ for (i = 0; i < HID_ABS_MAX; i++)
+ if (test_bit(absbits, i) &&
+ (ABS_TO_HID_MAP[i][1] >= HID_USAGE_GENERIC_X &&
+ ABS_TO_HID_MAP[i][1] <= HID_USAGE_GENERIC_WHEEL))
+ abs_count++;
+ return abs_count;
+}
+
static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_device *dev)
{
int abs_pages[TOP_ABS_PAGE][HID_ABS_MAX+1];
int rel_pages[TOP_REL_PAGE][HID_REL_MAX+1];
BYTE absbits[(ABS_MAX+7)/8];
BYTE relbits[(REL_MAX+7)/8];
- BYTE keybits[(KEY_MAX+7)/8];
BYTE *report_ptr;
INT i, descript_size;
INT report_size;
@@ -462,25 +504,12 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno));
return FALSE;
}
- if (ioctl(ext->base.device_fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits) == -1)
- {
- WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno, strerror(errno));
- return FALSE;
- }
descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
report_size = 0;
/* For now lump all buttons just into incremental usages, Ignore Keys */
- button_count = 0;
- for (i = BTN_MISC; i < KEY_MAX; i++)
- {
- if (test_bit(keybits, i))
- {
- ext->button_map[i] = button_count;
- button_count++;
- }
- }
+ button_count = count_buttons(ext->base.device_fd, ext->button_map);
if (button_count)
{
descript_size += sizeof(REPORT_BUTTONS);
@@ -1138,7 +1167,7 @@ static void try_add_device(struct udev_device *dev)
const char *subsystem;
const char *devnode;
WCHAR *serial = NULL;
- const char* gamepad = NULL;
+ BOOL is_gamepad = FALSE;
int fd;
if (!(devnode = udev_device_get_devnode(dev)))
@@ -1188,7 +1217,6 @@ static void try_add_device(struct udev_device *dev)
if (ioctl(fd, EVIOCGUNIQ(254), device_uid) >= 0 && device_uid[0])
serial = strdupAtoW(device_uid);
- gamepad = udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
vid = device_id.vendor;
pid = device_id.product;
version = device_id.version;
@@ -1198,18 +1226,31 @@ static void try_add_device(struct udev_device *dev)
WARN("Could not get device to query VID, PID, Version and Serial\n");
#endif
+ if (is_xbox_gamepad(vid, pid))
+ is_gamepad = TRUE;
+#ifdef HAS_PROPER_INPUT_HEADER
+ else
+ {
+ int axes=0, buttons=0;
+ axes = count_abs_axis(fd);
+ buttons = count_buttons(fd, NULL);
+ is_gamepad = (axes == 6 && buttons >= 14);
+ }
+#endif
+
+
TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
debugstr_a(devnode), vid, pid, version, debugstr_w(serial));
if (strcmp(subsystem, "hidraw") == 0)
{
- device = bus_create_hid_device(udev_driver_obj, hidraw_busidW, vid, pid, version, 0, serial, FALSE,
+ device = bus_create_hid_device(udev_driver_obj, hidraw_busidW, vid, pid, version, 0, serial, is_gamepad,
&GUID_DEVCLASS_HIDRAW, &hidraw_vtbl, sizeof(struct platform_private));
}
#ifdef HAS_PROPER_INPUT_HEADER
else if (strcmp(subsystem, "input") == 0)
{
- device = bus_create_hid_device(udev_driver_obj, lnxev_busidW, vid, pid, version, 0, serial, (gamepad != NULL),
+ device = bus_create_hid_device(udev_driver_obj, lnxev_busidW, vid, pid, version, 0, serial, is_gamepad,
&GUID_DEVCLASS_LINUXEVENT, &lnxev_vtbl, sizeof(struct wine_input_private));
}
#endif
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index 87d05f0..6334477 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -43,6 +43,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
WINE_DECLARE_DEBUG_CHANNEL(hid_report);
+#define VID_MICROSOFT 0x045e
+
+static const WORD PID_XBOX_CONTROLLERS[] = {
+ 0x0202, /* Xbox Controller */
+ 0x0285, /* Xbox Controller S */
+ 0x0289, /* Xbox Controller S */
+ 0x028e, /* Xbox360 Controller */
+ 0x028f, /* Xbox360 Wireless Controller */
+ 0x02d1, /* Xbox One Controller */
+ 0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */
+ 0x02e3, /* Xbox One Elite Controller */
+ 0x02e6, /* Wireless XBox Controller Dongle */
+ 0x02ea, /* Xbox One S Controller */
+ 0x0719, /* Xbox 360 Wireless Adapter */
+};
+
struct pnp_device
{
struct list entry;
@@ -673,6 +689,19 @@ DWORD check_bus_option(UNICODE_STRING *registry_path, const UNICODE_STRING *opti
return output;
}
+BOOL is_xbox_gamepad(WORD vid, WORD pid)
+{
+ int i;
+
+ if (vid != VID_MICROSOFT)
+ return FALSE;
+
+ for (i = 0; i < sizeof(PID_XBOX_CONTROLLERS)/sizeof(*PID_XBOX_CONTROLLERS); i++)
+ if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE;
+
+ return FALSE;
+}
+
NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
static const WCHAR udevW[] = {'\\','D','r','i','v','e','r','\\','U','D','E','V',0};
More information about the wine-cvs
mailing list