Rémi Bernon : dinput: Look for the PID device control output report.
Alexandre Julliard
julliard at winehq.org
Fri Oct 1 18:02:22 CDT 2021
Module: wine
Branch: master
Commit: ff7685dea4469dc099fe24a492ee73418c3aada4
URL: https://source.winehq.org/git/wine.git/?a=commit;h=ff7685dea4469dc099fe24a492ee73418c3aada4
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Fri Oct 1 09:31:01 2021 +0200
dinput: Look for the PID device control output report.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dinput/joystick_hid.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/dinput8/tests/hid.c | 6 ----
2 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index a6c6de3a889..b10ce7fc03b 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -78,6 +78,13 @@ struct extra_caps
LONG saturation;
};
+struct pid_control_report
+{
+ BYTE id;
+ ULONG collection;
+ ULONG control_coll;
+};
+
#define DEVICE_STATE_MAX_SIZE 1024
struct hid_joystick
@@ -102,6 +109,8 @@ struct hid_joystick
BYTE device_state_report_id;
BYTE device_state[DEVICE_STATE_MAX_SIZE];
+
+ struct pid_control_report pid_device_control;
};
static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface )
@@ -1176,6 +1185,12 @@ static BOOL hid_joystick_device_try_open( UINT32 handle, const WCHAR *path, HAND
instance->wUsagePage = caps->UsagePage;
instance->wUsage = caps->Usage;
+ count = ARRAY_SIZE(buttons);
+ status = HidP_GetSpecificButtonCaps( HidP_Output, HID_USAGE_PAGE_PID, 0,
+ PID_USAGE_DC_DEVICE_RESET, buttons, &count, preparsed_data );
+ if (status == HIDP_STATUS_SUCCESS && count > 0)
+ instance->guidFFDriver = IID_IDirectInputPIDDriver;
+
count = ARRAY_SIZE(buttons);
status = HidP_GetSpecificButtonCaps( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, 0, buttons, &count, preparsed_data );
if (status != HIDP_STATUS_SUCCESS) count = button_count = 0;
@@ -1398,6 +1413,67 @@ static BOOL init_data_format( struct hid_joystick *impl, struct hid_value_caps *
return DIENUM_CONTINUE;
}
+static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *caps,
+ DIDEVICEOBJECTINSTANCEW *instance, void *data )
+{
+ struct pid_control_report *device_control = &impl->pid_device_control;
+
+#define SET_COLLECTION( rep ) \
+ do \
+ { \
+ if (rep->collection) FIXME( "duplicate " #rep " report!\n" ); \
+ else rep->collection = DIDFT_GETINSTANCE( instance->dwType ); \
+ } while (0)
+
+#define SET_SUB_COLLECTION( rep, sub ) \
+ do { \
+ if (instance->wCollectionNumber != rep->collection) \
+ FIXME( "unexpected " #rep "." #sub " parent!\n" ); \
+ else if (rep->sub) \
+ FIXME( "duplicate " #rep "." #sub " collection!\n" ); \
+ else \
+ rep->sub = DIDFT_GETINSTANCE( instance->dwType ); \
+ } while (0)
+
+ if (instance->wUsagePage == HID_USAGE_PAGE_PID)
+ {
+ switch (instance->wUsage)
+ {
+ case PID_USAGE_DEVICE_CONTROL_REPORT: SET_COLLECTION( device_control ); break;
+ case PID_USAGE_DEVICE_CONTROL: SET_SUB_COLLECTION( device_control, control_coll ); break;
+ }
+ }
+
+#undef SET_SUB_COLLECTION
+#undef SET_COLLECTION
+
+ return DIENUM_CONTINUE;
+}
+
+static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *caps,
+ DIDEVICEOBJECTINSTANCEW *instance, void *data )
+{
+ struct pid_control_report *device_control = &impl->pid_device_control;
+
+ if (!(instance->dwType & DIDFT_OUTPUT)) return DIENUM_CONTINUE;
+
+#define SET_REPORT_ID( rep ) \
+ do \
+ { \
+ if (!rep->id) \
+ rep->id = instance->wReportId; \
+ else if (rep->id != instance->wReportId) \
+ FIXME( "multiple " #rep " report ids!\n" ); \
+ } while (0)
+
+ if (instance->wCollectionNumber == device_control->control_coll)
+ SET_REPORT_ID( device_control );
+
+#undef SET_REPORT_ID
+
+ return DIENUM_CONTINUE;
+}
+
static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID *guid, IDirectInputDevice8W **out )
{
static const DIPROPHEADER filter =
@@ -1485,6 +1561,20 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
impl->usages_buf = usages;
enum_objects( impl, &filter, DIDFT_ALL, init_objects, NULL );
+ enum_objects( impl, &filter, DIDFT_COLLECTION, init_pid_reports, NULL );
+ enum_objects( impl, &filter, DIDFT_NODATA, init_pid_caps, NULL );
+
+ TRACE( "device control id %u, coll %u, control coll %u\n", impl->pid_device_control.id,
+ impl->pid_device_control.collection, impl->pid_device_control.control_coll );
+
+ if (impl->pid_device_control.id)
+ {
+ impl->dev_caps.dwFlags |= DIDC_FORCEFEEDBACK;
+ impl->dev_caps.dwFFSamplePeriod = 1000000;
+ impl->dev_caps.dwFFMinTimeResolution = 1000000;
+ impl->dev_caps.dwHardwareRevision = 1;
+ impl->dev_caps.dwFFDriverVersion = 1;
+ }
format = impl->base.data_format.wine_df;
if (format->dwDataSize > DEVICE_STATE_MAX_SIZE)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index e6439ed8fe5..638d8f0aaeb 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5646,7 +5646,6 @@ static void test_force_feedback_joystick( void )
check_member_wstr( devinst, expect_devinst, tszInstanceName );
todo_wine
check_member_wstr( devinst, expect_devinst, tszProductName );
- todo_wine
check_member_guid( devinst, expect_devinst, guidFFDriver );
check_member( devinst, expect_devinst, "%04x", wUsagePage );
check_member( devinst, expect_devinst, "%04x", wUsage );
@@ -5655,20 +5654,15 @@ static void test_force_feedback_joystick( void )
hr = IDirectInputDevice8_GetCapabilities( device, &caps );
ok( hr == DI_OK, "IDirectInputDevice8_GetCapabilities returned %#x\n", hr );
check_member( caps, expect_caps, "%d", dwSize );
- todo_wine
check_member( caps, expect_caps, "%#x", dwFlags );
check_member( caps, expect_caps, "%#x", dwDevType );
check_member( caps, expect_caps, "%d", dwAxes );
check_member( caps, expect_caps, "%d", dwButtons );
check_member( caps, expect_caps, "%d", dwPOVs );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFSamplePeriod );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFMinTimeResolution );
check_member( caps, expect_caps, "%d", dwFirmwareRevision );
- todo_wine
check_member( caps, expect_caps, "%d", dwHardwareRevision );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFDriverVersion );
prop_dword.dwData = 0xdeadbeef;
More information about the wine-cvs
mailing list