[PATCH 1/5] dinput: return fake DIPROP_GUIDANDPATH property for linux joysticks
Some Ubisoft titles use the property to check if a dinput gamepad is also an xinput device. Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- A similar patch for the SDL backend has been already accepted into Proton. And I have been asked to adapt it for other backends. is_xinput_device() is based on the code from winebus.sys. In future, the xinput device detection should be kept in sync as much as possible. --- dlls/dinput/dinput_main.c | 1 + dlls/dinput/joystick.c | 31 +++++++++++++++++++++++++++++++ dlls/dinput/joystick_linux.c | 24 ++++++++++++++++++++++++ dlls/dinput/joystick_private.h | 1 + 4 files changed, 57 insertions(+) diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index acf2cf3d23..c02bafad10 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 f758092dab..433348cd04 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 2480bc2b76..7e01f90843 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 e758cacf6d..b786c84dec 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 */ -- 2.17.2 (Apple Git-113)
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/joystick_linuxinput.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index fdfbc7f372..e3371b9f44 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -57,6 +57,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h" #include "dinput_private.h" @@ -1034,6 +1035,29 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF 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); } -- 2.17.2 (Apple Git-113)
Hi, While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53279 Your paranoid android. === debian9 (64 bit WoW report) === dinput: keyboard.c:153: Test failed: Keyboard event not processed, skipping test
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com> On Wed, Jun 05, 2019 at 12:53:45AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/joystick_linuxinput.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index fdfbc7f372..e3371b9f44 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -57,6 +57,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h"
#include "dinput_private.h" @@ -1034,6 +1035,29 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF 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); } -- 2.17.2 (Apple Git-113)
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/joystick_osx.c | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c index 540d16b2da..ce3b87703a 100644 --- a/dlls/dinput/joystick_osx.c +++ b/dlls/dinput/joystick_osx.c @@ -85,6 +85,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h" #include "dinput_private.h" @@ -124,6 +125,11 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W JoystickGenericImpl, base), JoystickImpl, generic); } +static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This) +{ + return &This->generic.base.IDirectInputDevice8W_iface; +} + typedef struct _EffectImpl { IDirectInputEffect IDirectInputEffect_iface; LONG ref; @@ -1336,6 +1342,53 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF return DIERR_DEVICENOTREG; } +static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); + _dump_DIPROPHEADER(pdiph); + + if (!IS_DIPROP(rguid)) return DI_OK; + + switch (LOWORD(rguid)) { + 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','_','%','i',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + IOHIDDeviceRef device = get_device_ref(This->id); + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); + WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); + + 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, This->id); + + 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); + } + + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); + return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); +} + static HRESULT osx_set_autocenter(JoystickImpl *This, const DIPROPDWORD *header) { @@ -1518,7 +1571,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = IDirectInputDevice2AImpl_Release, JoystickAGenericImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, - JoystickAGenericImpl_GetProperty, + JoystickAImpl_GetProperty, JoystickAImpl_SetProperty, IDirectInputDevice2AImpl_Acquire, IDirectInputDevice2AImpl_Unacquire, @@ -1554,7 +1607,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = IDirectInputDevice2WImpl_Release, JoystickWGenericImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, - JoystickWGenericImpl_GetProperty, + JoystickWImpl_GetProperty, JoystickWImpl_SetProperty, IDirectInputDevice2WImpl_Acquire, IDirectInputDevice2WImpl_Unacquire, -- 2.17.2 (Apple Git-113)
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com> On Wed, Jun 05, 2019 at 12:53:46AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/joystick_osx.c | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c index 540d16b2da..ce3b87703a 100644 --- a/dlls/dinput/joystick_osx.c +++ b/dlls/dinput/joystick_osx.c @@ -85,6 +85,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h"
#include "dinput_private.h" @@ -124,6 +125,11 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W JoystickGenericImpl, base), JoystickImpl, generic); }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This) +{ + return &This->generic.base.IDirectInputDevice8W_iface; +} + typedef struct _EffectImpl { IDirectInputEffect IDirectInputEffect_iface; LONG ref; @@ -1336,6 +1342,53 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF return DIERR_DEVICENOTREG; }
+static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); + _dump_DIPROPHEADER(pdiph); + + if (!IS_DIPROP(rguid)) return DI_OK; + + switch (LOWORD(rguid)) { + 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','_','%','i',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + IOHIDDeviceRef device = get_device_ref(This->id); + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); + WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); + + 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, This->id); + + 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); + } + + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); + return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); +} + static HRESULT osx_set_autocenter(JoystickImpl *This, const DIPROPDWORD *header) { @@ -1518,7 +1571,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = IDirectInputDevice2AImpl_Release, JoystickAGenericImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, - JoystickAGenericImpl_GetProperty, + JoystickAImpl_GetProperty, JoystickAImpl_SetProperty, IDirectInputDevice2AImpl_Acquire, IDirectInputDevice2AImpl_Unacquire, @@ -1554,7 +1607,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = IDirectInputDevice2WImpl_Release, JoystickWGenericImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, - JoystickWGenericImpl_GetProperty, + JoystickWImpl_GetProperty, JoystickWImpl_SetProperty, IDirectInputDevice2WImpl_Acquire, IDirectInputDevice2WImpl_Unacquire, -- 2.17.2 (Apple Git-113)
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/tests/joystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index c07e821fb0..f35b07e90b 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -402,7 +402,7 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef) dpg.diph.dwHow = DIPH_DEVICE; hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_GUIDANDPATH, &dpg.diph); - todo_wine ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr); + ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr); hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL); ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned " -- 2.17.2 (Apple Git-113)
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com> On Wed, Jun 05, 2019 at 12:53:47AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- dlls/dinput/tests/joystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index c07e821fb0..f35b07e90b 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -402,7 +402,7 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef) dpg.diph.dwHow = DIPH_DEVICE;
hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_GUIDANDPATH, &dpg.diph); - todo_wine ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr); + ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr);
hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL); ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned " -- 2.17.2 (Apple Git-113)
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- I have split the patch from the previous one mainly because I am not sure about it. The whole patchset is basicaly a semi-stub to treak some Ubisoft games (such as AC: Unity, Far Cry 5) into exclusively using xinput. This is the only half-way useful test I am able to come up with the fake implementation could pass. --- dlls/dinput/tests/joystick.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index f35b07e90b..f009ef347b 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -404,6 +404,22 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef) hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_GUIDANDPATH, &dpg.diph); ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr); + { + static const WCHAR formatW[] = {'\\','\\','?','\\','%','*','[','^','#',']','#','v','i','d','_', + '%','0','4','x','&','p','i','d','_','%','0','4','x',0}; + static const WCHAR miW[] = {'m','i','_',0}; + static const WCHAR igW[] = {'i','g','_',0}; + int vid, pid; + + _wcslwr(dpg.wszPath); + count = swscanf(dpg.wszPath, formatW, &vid, &pid); + ok(count == 2, "DIPROP_GUIDANDPATH path has wrong format. Expected count: 2 Got: %i Path: %s\n", + count, wine_dbgstr_w(dpg.wszPath)); + ok(wcsstr(dpg.wszPath, miW) != 0 || wcsstr(dpg.wszPath, igW) != 0, + "DIPROP_GUIDANDPATH path should contain either 'ig_' or 'mi_' substring. Path: %s\n", + wine_dbgstr_w(dpg.wszPath)); + } + hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL); ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned " "E_POINTER, returned: %08x\n", hr); -- 2.17.2 (Apple Git-113)
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com> On Wed, Jun 05, 2019 at 12:53:48AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- I have split the patch from the previous one mainly because I am not sure about it. The whole patchset is basicaly a semi-stub to treak some Ubisoft games (such as AC: Unity, Far Cry 5) into exclusively using xinput. This is the only half-way useful test I am able to come up with the fake implementation could pass. --- dlls/dinput/tests/joystick.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index f35b07e90b..f009ef347b 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -404,6 +404,22 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef) hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_GUIDANDPATH, &dpg.diph); ok(SUCCEEDED(hr), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr);
+ { + static const WCHAR formatW[] = {'\\','\\','?','\\','%','*','[','^','#',']','#','v','i','d','_', + '%','0','4','x','&','p','i','d','_','%','0','4','x',0}; + static const WCHAR miW[] = {'m','i','_',0}; + static const WCHAR igW[] = {'i','g','_',0}; + int vid, pid; + + _wcslwr(dpg.wszPath); + count = swscanf(dpg.wszPath, formatW, &vid, &pid); + ok(count == 2, "DIPROP_GUIDANDPATH path has wrong format. Expected count: 2 Got: %i Path: %s\n", + count, wine_dbgstr_w(dpg.wszPath)); + ok(wcsstr(dpg.wszPath, miW) != 0 || wcsstr(dpg.wszPath, igW) != 0, + "DIPROP_GUIDANDPATH path should contain either 'ig_' or 'mi_' substring. Path: %s\n", + wine_dbgstr_w(dpg.wszPath)); + } + hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL); ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned " "E_POINTER, returned: %08x\n", hr); -- 2.17.2 (Apple Git-113)
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com> --- Alexandre, I think it makes sense to squash all 5 of these down to a single commit. On Wed, Jun 05, 2019 at 12:53:44AM +0300, Alexey Prokhin wrote:
Some Ubisoft titles use the property to check if a dinput gamepad is also an xinput device.
Signed-off-by: Alexey Prokhin <alexey(a)prokhin.ru> --- A similar patch for the SDL backend has been already accepted into Proton. And I have been asked to adapt it for other backends.
is_xinput_device() is based on the code from winebus.sys. In future, the xinput device detection should be kept in sync as much as possible. --- dlls/dinput/dinput_main.c | 1 + dlls/dinput/joystick.c | 31 +++++++++++++++++++++++++++++++ dlls/dinput/joystick_linux.c | 24 ++++++++++++++++++++++++ dlls/dinput/joystick_private.h | 1 + 4 files changed, 57 insertions(+)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index acf2cf3d23..c02bafad10 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 f758092dab..433348cd04 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 2480bc2b76..7e01f90843 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 e758cacf6d..b786c84dec 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 */ -- 2.17.2 (Apple Git-113)
participants (3)
-
Alexey Prokhin -
Andrew Eikum -
Marvin