diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index a690505aa57..0855cb41cd5 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -48,6 +48,7 @@ #include "objbase.h" #include "rpcproxy.h" #include "initguid.h" +#include "devguid.h" #include "dinput_private.h" #include "device_private.h" #include "dinputd.h" diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c index f758092dab6..433348cd043 100644 --- a/dlls/dinput/joystick.c +++ b/dlls/dinput/joystick.c @@ -34,6 +34,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput); +#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) */ + 0x02e0, /* Xbox One X Controller */ + 0x02e3, /* Xbox One Elite Controller */ + 0x02e6, /* Wireless XBox Controller Dongle */ + 0x02ea, /* Xbox One S Controller */ + 0x02fd, /* Xbox One S Controller (Firmware 2017) */ + 0x0719, /* Xbox 360 Wireless Adapter */ +}; + static inline JoystickGenericImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface) { return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), JoystickGenericImpl, base); @@ -281,6 +299,19 @@ BOOL device_disabled_registry(const char* name) return do_disable; } +BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) +{ + int i; + + if (vid == VID_MICROSOFT) + { + for (i = 0; i < ARRAY_SIZE(PID_XBOX_CONTROLLERS); i++) + if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE; + } + + return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14); +} + /****************************************************************************** * SetProperty : change input device properties */ diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c index 2480bc2b764..7e01f90843b 100644 --- a/dlls/dinput/joystick_linux.c +++ b/dlls/dinput/joystick_linux.c @@ -59,6 +59,7 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" +#include "devguid.h" #include "dinput.h" #include "dinput_private.h" @@ -742,6 +743,29 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface break; } + case (DWORD_PTR) DIPROP_GUIDANDPATH: + { + static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&', + 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = This->joydev->vendor_id; + WORD pid = This->joydev->product_id; + + if (!pid || !vid) + return DIERR_UNSUPPORTED; + + is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); + pd->guidClass = GUID_DEVCLASS_HIDCLASS; + sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid)); + + TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); + break; + } + default: return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); } diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h index e758cacf6df..b786c84decb 100644 --- a/dlls/dinput/joystick_private.h +++ b/dlls/dinput/joystick_private.h @@ -96,5 +96,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LP DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN; void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN; +BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) DECLSPEC_HIDDEN; #endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */