Some Ubisoft titles use the property to check if a dinput gamepad is also an xinput device.
Signed-off-by: Alexey Prokhin alexey@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 */
Signed-off-by: Alexey Prokhin alexey@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); }
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@codeweavers.com
On Wed, Jun 05, 2019 at 12:53:45AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin alexey@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@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,
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Wed, Jun 05, 2019 at 12:53:46AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin alexey@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@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 "
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Wed, Jun 05, 2019 at 12:53:47AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin alexey@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@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);
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Wed, Jun 05, 2019 at 12:53:48AM +0300, Alexey Prokhin wrote:
Signed-off-by: Alexey Prokhin alexey@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@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@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)