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