dinput: Implement device creation using product GUID.

This fixes Far Cry Primal controller discovery.

Signed-off-by: Arkadiusz Hiler <ahiler@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Arkadiusz Hiler 2021-03-23 20:00:36 +02:00 committed by Alexandre Julliard
parent c17cd0fcab
commit 0a82d891fc
5 changed files with 60 additions and 2 deletions

View file

@ -717,7 +717,7 @@ HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo(
index = pd.dwData;
/* Return joystick */
pdidi->guidInstance = This->guidInstance;
pdidi->guidInstance = This->base.guid;
pdidi->guidProduct = This->guidProduct;
/* we only support traditional joysticks for now */
pdidi->dwDevType = This->devcaps.dwDevType;
@ -761,7 +761,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo(
index = pd.dwData;
/* Return joystick */
pdidi->guidInstance = This->guidInstance;
pdidi->guidInstance = This->base.guid;
pdidi->guidProduct = This->guidProduct;
/* we only support traditional joysticks for now */
pdidi->dwDevType = This->devcaps.dwDevType;

View file

@ -598,6 +598,7 @@ static unsigned short get_joystick_index(REFGUID guid)
{
GUID wine_joystick = DInput_Wine_Joystick_GUID;
GUID dev_guid = *guid;
INT i;
wine_joystick.Data3 = 0;
dev_guid.Data3 = 0;
@ -608,6 +609,9 @@ static unsigned short get_joystick_index(REFGUID guid)
/* for the wine joystick GUIDs use the index stored in Data3 */
if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
for(i = 0; i < joystick_devices_count; i++)
if(IsEqualGUID(&joystick_devices[i].guid_product, guid)) return i;
return MAX_JOYSTICKS;
}
@ -790,6 +794,9 @@ static HRESULT WINAPI JoystickLinuxAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A ifa
fill_joystick_dideviceinstanceA( ddi, This->generic.base.dinput->dwVersion,
get_joystick_index(&This->generic.base.guid) );
ddi->guidInstance = This->generic.base.guid;
return DI_OK;
}
@ -806,6 +813,9 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W ifa
fill_joystick_dideviceinstanceW( ddi, This->generic.base.dinput->dwVersion,
get_joystick_index(&This->generic.base.guid) );
ddi->guidInstance = This->generic.base.guid;
return DI_OK;
}

View file

@ -612,6 +612,7 @@ static unsigned short get_joystick_index(REFGUID guid)
{
GUID wine_joystick = DInput_Wine_Joystick_Base_GUID;
GUID dev_guid = *guid;
INT i;
wine_joystick.Data3 = 0;
dev_guid.Data3 = 0;
@ -622,6 +623,9 @@ static unsigned short get_joystick_index(REFGUID guid)
/* for the wine joystick GUIDs use the index stored in Data3 */
if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3 - DInput_Wine_Joystick_Base_GUID.Data3;
for(i = 0; i < have_joydevs; i++)
if(IsEqualGUID(&joydevs[i].guid_product, guid)) return i;
return MAX_JOYDEV;
}
@ -1450,6 +1454,9 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface,
fill_joystick_dideviceinstanceA(pdidi, This->generic.base.dinput->dwVersion,
get_joystick_index(&This->generic.base.guid));
pdidi->guidInstance = This->generic.base.guid;
return DI_OK;
}
@ -1467,6 +1474,9 @@ static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface,
fill_joystick_dideviceinstanceW(pdidi, This->generic.base.dinput->dwVersion,
get_joystick_index(&This->generic.base.guid));
pdidi->guidInstance = This->generic.base.guid;
return DI_OK;
}

View file

@ -1322,6 +1322,10 @@ static unsigned short get_joystick_index(REFGUID guid)
{
GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
GUID dev_guid = *guid;
GUID prod_guid = *guid;
IOHIDDeviceRef device;
int joystick_devices_count;
INT i;
wine_joystick.Data3 = 0;
dev_guid.Data3 = 0;
@ -1332,6 +1336,18 @@ static unsigned short get_joystick_index(REFGUID guid)
/* for the wine joystick GUIDs use the index stored in Data3 */
if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
prod_guid.Data1 = 0;
if(IsEqualGUID(&DInput_PIDVID_Product_GUID, &prod_guid))
{
joystick_devices_count = find_joystick_devices();
for(i = 0; i < joystick_devices_count; i++)
{
device = get_device_ref(i);
if(guid->Data1 == make_vid_pid(device))
return i;
}
}
return 0xffff;
}

View file

@ -197,12 +197,14 @@ struct enum_data
{
IDirectInputA *pDI;
HWND hwnd;
BOOL tested_product_creation;
};
static BOOL CALLBACK enum_devices(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
{
struct enum_data *data = pvRef;
IDirectInputDeviceA *device, *obj = NULL;
DIDEVICEINSTANCEA ddi2;
HRESULT hr;
hr = IDirectInput_GetDeviceStatus(data->pDI, &lpddi->guidInstance);
@ -226,6 +228,24 @@ static BOOL CALLBACK enum_devices(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
IUnknown_Release(obj);
IUnknown_Release(device);
if (!IsEqualGUID(&lpddi->guidInstance, &lpddi->guidProduct))
{
data->tested_product_creation = TRUE;
hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidProduct, &device, NULL);
ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
ddi2.dwSize = sizeof(ddi2);
hr = IDirectInputDevice_GetDeviceInfo(device, &ddi2);
ok(SUCCEEDED(hr), "IDirectInput_GetDeviceInfo failed: %08x\n", hr);
ok(IsEqualGUID(&lpddi->guidProduct, &ddi2.guidProduct), "Product GUIDs do not match. Expected %s, got %s\n", debugstr_guid(&lpddi->guidProduct), debugstr_guid(&ddi2.guidProduct));
ok(IsEqualGUID(&ddi2.guidProduct, &ddi2.guidInstance), "Instance GUID should equal product GUID. Expected %s, got %s\n", debugstr_guid(&ddi2.guidProduct), debugstr_guid(&ddi2.guidInstance));
/* we cannot compare guidInstances as we may get a different device */
IUnknown_Release(device);
}
}
return DIENUM_CONTINUE;
}
@ -263,9 +283,11 @@ static void device_tests(void)
data.pDI = pDI;
data.hwnd = hwnd;
data.tested_product_creation = FALSE;
hr = IDirectInput_EnumDevices(pDI, 0, enum_devices, &data, DIEDFL_ALLDEVICES);
ok(SUCCEEDED(hr), "IDirectInput_EnumDevices() failed: %08x\n", hr);
if (!data.tested_product_creation) winetest_skip("Device creation using product GUID not tested\n");
/* If GetDeviceStatus returns DI_OK the device must exist */
hr = IDirectInput_GetDeviceStatus(pDI, &GUID_Joystick);