-- v3: dinput: Once again support creating joystick device with GUID_Joystick. dinput: Derive DIPROP_JOYSTICKID from device path enumeration. dinput/tests: Add tests for joystick id.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/dinput/tests/driver_bus.c | 2 +- dlls/dinput/tests/driver_hid.c | 2 - dlls/dinput/tests/hid.c | 3 +- dlls/dinput/tests/joystick8.c | 154 ++++++++++++++++++++++++++++++++- 4 files changed, 156 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c index cf42a1bcf6e..320b47057a5 100644 --- a/dlls/dinput/tests/driver_bus.c +++ b/dlls/dinput/tests/driver_bus.c @@ -563,7 +563,7 @@ static NTSTATUS remove_child_device( struct func_device *impl, DEVICE_OBJECT *de for (i = 0; i < impl->devices->Count; ++i) if (impl->devices->Objects[i] == device) break; if (i == impl->devices->Count) status = STATUS_NOT_FOUND; - else impl->devices->Objects[i] = impl->devices->Objects[impl->devices->Count--]; + else impl->devices->Objects[i] = impl->devices->Objects[--impl->devices->Count]; KeReleaseSpinLock( &impl->base.lock, irql );
return status; diff --git a/dlls/dinput/tests/driver_hid.c b/dlls/dinput/tests/driver_hid.c index 7b20af07493..5d92c8b230a 100644 --- a/dlls/dinput/tests/driver_hid.c +++ b/dlls/dinput/tests/driver_hid.c @@ -57,8 +57,6 @@ static void check_device( DEVICE_OBJECT *device )
ok( device == impl->expect_hid_fdo, "got device %p\n", device ); ok( device->DriverObject == expect_driver, "got DriverObject %p\n", device->DriverObject ); - if (!device->NextDevice) ok( device == impl->expect_hid_fdo, "got device %p\n", device ); - else ok( device->NextDevice == impl->expect_hid_fdo, "got NextDevice %p\n", device->NextDevice ); ok( !device->AttachedDevice, "got AttachedDevice %p\n", device->AttachedDevice );
ok( ext->MiniDeviceExtension == impl->expect_hid_ext, "got MiniDeviceExtension %p\n", ext->MiniDeviceExtension ); diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 5e48050738b..06f1e4ee7e5 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -719,7 +719,8 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) NULL, OPEN_EXISTING, 0, NULL ); ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); ret = sync_ioctl( control, IOCTL_WINETEST_REMOVE_DEVICE, desc, sizeof(*desc), NULL, 0, 5000 ); - ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() ); + ok( ret || (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_NO_SUCH_DEVICE), + "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() ); CloseHandle( control );
if (!ret) return; diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 3201a3608d2..e10501124ad 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -5965,6 +5965,158 @@ static void test_rawinput_desktop( const char *path, BOOL input ) DestroyWindow( hwnd ); }
+struct select_default_instance_data +{ + IDirectInput8W *di8; + DIDEVICEINSTANCEW default_instance; + BOOL default_instance_found; +}; + +static BOOL CALLBACK select_default_instance( const DIDEVICEINSTANCEW *devinst, void *context ) +{ + DIPROPGUIDANDPATH prop_guid_path = + { + .diph = + { + .dwSize = sizeof(DIPROPGUIDANDPATH), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + + DIPROPDWORD prop_dword = + { + .diph = + { + .dwSize = sizeof(DIPROPDWORD), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + struct select_default_instance_data *d = context; + IDirectInputDevice8W *device; + HRESULT hr; + + hr = IDirectInput8_CreateDevice( d->di8, &devinst->guidInstance, &device, NULL ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + todo_wine ok( prop_dword.dwData < 100, "got %lu.\n", prop_dword.dwData ); + + hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + trace( "%s, id %lu, inst %s, path %s.\n", debugstr_w(devinst->tszInstanceName), prop_dword.dwData, + debugstr_guid(&devinst->guidInstance), debugstr_w(prop_guid_path.wszPath) ); + if (!prop_dword.dwData) + { + ok( !d->default_instance_found, "duplicate joystick with id 0.\n" ); + d->default_instance = *devinst; + d->default_instance_found = TRUE; + } + IDirectInputDevice8_Release( device ); + return DIENUM_CONTINUE; +} + +static void test_joystick_id(void) +{ +#include "psh_hid_macros.h" + const unsigned char report_desc[] = + { + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Physical), + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 6), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_SIZE(1, 1), + REPORT_COUNT(1, 8), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + END_COLLECTION, + }; + C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN); +#include "pop_hid_macros.h" + struct hid_device_desc desc = + { + .use_report_id = TRUE, + .caps = { .InputReportByteLength = 1 }, + }; + struct hid_device_desc desc2; + + DIPROPDWORD prop_dword = + { + .diph = + { + .dwSize = sizeof(DIPROPDWORD), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + struct select_default_instance_data d = { NULL }; + IDirectInputDevice8W *device; + IDirectInput8W *di8; + HRESULT hr; + + cleanup_registry_keys(); + + hr = DirectInput8Create( instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W, (void **)&di8, NULL ); + if (FAILED(hr)) + { + win_skip( "DirectInput8Create returned %#lx.\n", hr ); + return; + } + + desc.report_descriptor_len = sizeof(report_desc); + memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); + fill_context( desc.context, ARRAY_SIZE(desc.context) ); + + desc.attributes = default_attributes; + desc2 = desc; + desc2.attributes.ProductID++; + if (!hid_device_start( &desc, 1 )) goto done; + if (!hid_device_start( &desc2, 1 )) goto done; + + d.di8 = di8; + hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_GAMECTRL, select_default_instance, &d, DIEDFL_ALLDEVICES ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + + hr = IDirectInput8_CreateDevice( di8, &GUID_Joystick, &device, NULL ); + if (d.default_instance_found) + { + ok( hr == DI_OK, "got %#lx.\n", hr ); + hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + ok( !prop_dword.dwData, "got %lu.\n", prop_dword.dwData ); + IDirectInputDevice8_Release( device ); + } + else + { + ok( hr == DIERR_DEVICENOTREG, "got %#lx.\n", hr ); + } + + hid_device_stop( &desc, 1 ); + + memset( &d, 0, sizeof(d) ); + d.di8 = di8; + hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_GAMECTRL, select_default_instance, &d, DIEDFL_ALLDEVICES ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + ok( !d.default_instance_found, "found joystick id 0.\n" ); + hr = IDirectInput8_CreateDevice( di8, &GUID_Joystick, &device, NULL ); + ok( hr == DIERR_DEVICENOTREG, "got %#lx.\n", hr ); + +done: + IDirectInput8_Release( di8 ); + hid_device_stop( &desc, 1 ); + hid_device_stop( &desc2, 1 ); + cleanup_registry_keys(); +} + START_TEST( joystick8 ) { char **argv; @@ -5976,11 +6128,11 @@ START_TEST( joystick8 )
dinput_test_init(); if (!bus_device_start()) goto done; - winetest_mute_threshold = 3;
if (test_device_types( 0x800 )) { + test_joystick_id(); /* This needs to be done before doing anything involving dinput.dll * on Windows, or the tests will fail, dinput8.dll is fine though. */ test_winmm_joystick();
From: Paul Gofman pgofman@codeweavers.com
--- dlls/dinput/joystick_hid.c | 40 ++++++++++++++++++++++++++++++++++- dlls/dinput/tests/joystick8.c | 16 ++++++++------ 2 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index e492fa51bbf..b9cec0ba14c 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -239,6 +239,42 @@ struct hid_joystick_effect char *set_envelope_buf; };
+struct joystick_device +{ + WCHAR device_path[MAX_PATH]; +}; + +static CRITICAL_SECTION joystick_devices_crit; +static CRITICAL_SECTION_DEBUG joystick_devices_crit_debug = +{ + 0, 0, &joystick_devices_crit, + { &joystick_devices_crit_debug.ProcessLocksList, &joystick_devices_crit_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": joystick_devices_crit") } +}; +static CRITICAL_SECTION joystick_devices_crit = { &joystick_devices_crit_debug, -1, 0, 0, 0, 0 }; + +static struct joystick_device *joystick_devices; +static unsigned int joystick_device_count; + +static unsigned int get_joystick_index( const WCHAR *device_path ) +{ + unsigned int i; + + EnterCriticalSection( &joystick_devices_crit ); + for (i = 0; i < joystick_device_count; ++i) + if (!wcsicmp( joystick_devices[i].device_path, device_path )) break; + + if (i == joystick_device_count) + { + ++joystick_device_count; + joystick_devices = realloc( joystick_devices, sizeof(*joystick_devices) * joystick_device_count ); + wcscpy( joystick_devices[i].device_path, device_path ); + } + LeaveCriticalSection( &joystick_devices_crit ); + return i; +} + + static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface ) { return CONTAINING_RECORD( iface, struct hid_joystick_effect, IDirectInputEffect_iface ); @@ -805,7 +841,7 @@ static HRESULT hid_joystick_get_property( IDirectInputDevice8W *iface, DWORD pro case (DWORD_PTR)DIPROP_JOYSTICKID: { DIPROPDWORD *value = (DIPROPDWORD *)header; - value->dwData = impl->base.instance.guidInstance.Data3; + value->dwData = get_joystick_index( impl->device_path ); return DI_OK; } case (DWORD_PTR)DIPROP_GUIDANDPATH: @@ -1626,6 +1662,8 @@ static HRESULT hid_joystick_device_open( int index, const GUID *guid, DIDEVICEIN attrs, caps, instance, version ))) continue; } + /* Assign joystick index if the device path is first seen. */ + get_joystick_index( detail->DevicePath );
/* enumerate device by GUID */ if (IsEqualGUID( guid, &instance->guidProduct ) || IsEqualGUID( guid, &instance->guidInstance )) break; diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index e10501124ad..516d3257876 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -2077,7 +2077,6 @@ static void test_simple_joystick( DWORD version ) prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); ok( hr == DI_OK, "GetProperty DIPROP_JOYSTICKID returned %#lx\n", hr ); - todo_wine ok( prop_dword.dwData == 0, "got %#lx expected 0\n", prop_dword.dwData );
prop_dword.dwData = 0xdeadbeef; @@ -6001,7 +6000,7 @@ static BOOL CALLBACK select_default_instance( const DIDEVICEINSTANCEW *devinst, ok( hr == DI_OK, "got hr %#lx.\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); ok( hr == DI_OK, "got hr %#lx.\n", hr ); - todo_wine ok( prop_dword.dwData < 100, "got %lu.\n", prop_dword.dwData ); + ok( prop_dword.dwData < 100, "got %lu.\n", prop_dword.dwData );
hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph ); ok( hr == DI_OK, "got hr %#lx.\n", hr ); @@ -6089,11 +6088,14 @@ static void test_joystick_id(void) hr = IDirectInput8_CreateDevice( di8, &GUID_Joystick, &device, NULL ); if (d.default_instance_found) { - ok( hr == DI_OK, "got %#lx.\n", hr ); - hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); - ok( hr == DI_OK, "got hr %#lx.\n", hr ); - ok( !prop_dword.dwData, "got %lu.\n", prop_dword.dwData ); - IDirectInputDevice8_Release( device ); + todo_wine ok( hr == DI_OK, "got %#lx.\n", hr ); + if (hr == DI_OK) + { + hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + ok( !prop_dword.dwData, "got %lu.\n", prop_dword.dwData ); + IDirectInputDevice8_Release( device ); + } } else {
From: Paul Gofman pgofman@codeweavers.com
--- dlls/dinput/joystick_hid.c | 16 ++++++++++++++++ dlls/dinput/tests/joystick8.c | 13 +++++-------- 2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index b9cec0ba14c..0424e6f0dbf 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -274,6 +274,15 @@ static unsigned int get_joystick_index( const WCHAR *device_path ) return i; }
+static BOOL get_default_joystick_device_path( WCHAR *device_path ) +{ + BOOL ret; + + EnterCriticalSection( &joystick_devices_crit ); + if ((ret = !!joystick_device_count)) wcscpy( device_path, joystick_devices[0].device_path ); + LeaveCriticalSection( &joystick_devices_crit ); + return ret; +}
static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface ) { @@ -2080,8 +2089,15 @@ HRESULT hid_joystick_create_device( struct dinput *dinput, const GUID *guid, IDi impl->base.read_event = CreateEventW( NULL, TRUE, FALSE, NULL );
if (memcmp( device_path_guid.Data4, guid->Data4, sizeof(device_path_guid.Data4) )) + { + /* Let hid_joystick_device_open() populate joystick devices before checking for default joystick GUID. */ hr = hid_joystick_device_open( -1, guid, &impl->base.instance, impl->device_path, &impl->device, &impl->preparsed, &attrs, &impl->caps, dinput->dwVersion ); + if (hr == DIERR_DEVICENOTREG && IsEqualGUID( guid, &GUID_Joystick ) + && get_default_joystick_device_path( impl->device_path )) + hr = hid_joystick_device_try_open( impl->device_path, &impl->device, &impl->preparsed, &attrs, + &impl->caps, &impl->base.instance, dinput->dwVersion ); + } else { wcscpy( impl->device_path, *(const WCHAR **)guid ); diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 516d3257876..afc24e49c8f 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -6088,14 +6088,11 @@ static void test_joystick_id(void) hr = IDirectInput8_CreateDevice( di8, &GUID_Joystick, &device, NULL ); if (d.default_instance_found) { - todo_wine ok( hr == DI_OK, "got %#lx.\n", hr ); - if (hr == DI_OK) - { - hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); - ok( hr == DI_OK, "got hr %#lx.\n", hr ); - ok( !prop_dword.dwData, "got %lu.\n", prop_dword.dwData ); - IDirectInputDevice8_Release( device ); - } + ok( hr == DI_OK, "got %#lx.\n", hr ); + hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph ); + ok( hr == DI_OK, "got hr %#lx.\n", hr ); + ok( !prop_dword.dwData, "got %lu.\n", prop_dword.dwData ); + IDirectInputDevice8_Release( device ); } else {