[PATCH 04/11] dinput: Implement support for the PID effect set envelope report.

Rémi Bernon rbernon at codeweavers.com
Fri Oct 8 02:50:22 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/joystick_hid.c | 73 +++++++++++++++++++++++++++++++++++++-
 dlls/dinput8/tests/hid.c   |  2 --
 2 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 7ea8ea3cd0e..735b3800b31 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -114,6 +114,16 @@ struct pid_set_periodic
     struct hid_value_caps *offset_caps;
 };
 
+struct pid_set_envelope
+{
+    BYTE id;
+    ULONG collection;
+    struct hid_value_caps *attack_level_caps;
+    struct hid_value_caps *attack_time_caps;
+    struct hid_value_caps *fade_level_caps;
+    struct hid_value_caps *fade_time_caps;
+};
+
 #define DEVICE_STATE_MAX_SIZE 1024
 
 struct hid_joystick
@@ -147,6 +157,7 @@ struct hid_joystick
     struct pid_control_report pid_effect_control;
     struct pid_effect_update pid_effect_update;
     struct pid_set_periodic pid_set_periodic;
+    struct pid_set_envelope pid_set_envelope;
 };
 
 static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface )
@@ -175,7 +186,7 @@ struct hid_joystick_effect
 
     char *effect_control_buf;
     char *effect_update_buf;
-    char *type_specific_buf[1];
+    char *type_specific_buf[2];
 };
 
 static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface )
@@ -1113,6 +1124,7 @@ static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, D
     struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
     struct pid_effect_update *effect_update = &impl->pid_effect_update;
     struct pid_set_periodic *set_periodic = &impl->pid_set_periodic;
+    struct pid_set_envelope *set_envelope = &impl->pid_set_envelope;
     PHIDP_PREPARSED_DATA preparsed = impl->preparsed;
     HIDP_BUTTON_CAPS button;
     ULONG type, collection;
@@ -1197,6 +1209,16 @@ static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, D
         if (set_periodic->phase_caps) info->dwDynamicParams |= DIEP_TYPESPECIFICPARAMS;
     }
 
+    if ((type == DIEFT_PERIODIC || type == DIEFT_RAMPFORCE || type == DIEFT_CONSTANTFORCE) &&
+        (collection = set_envelope->collection))
+    {
+        info->dwDynamicParams |= DIEP_ENVELOPE;
+        if (set_envelope->attack_level_caps) type |= DIEFT_FFATTACK;
+        if (set_envelope->attack_time_caps) type |= DIEFT_FFATTACK;
+        if (set_envelope->fade_level_caps) type |= DIEFT_FFFADE;
+        if (set_envelope->fade_time_caps) type |= DIEFT_FFFADE;
+    }
+
     info->guid = *guid;
     info->dwEffType = type;
     info->dwStaticParams = info->dwDynamicParams;
@@ -1846,6 +1868,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *
     struct pid_control_report *effect_control = &impl->pid_effect_control;
     struct pid_effect_update *effect_update = &impl->pid_effect_update;
     struct pid_set_periodic *set_periodic = &impl->pid_set_periodic;
+    struct pid_set_envelope *set_envelope = &impl->pid_set_envelope;
 
 #define SET_COLLECTION( rep )                                          \
     do                                                                 \
@@ -1872,6 +1895,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *
         case PID_USAGE_EFFECT_OPERATION_REPORT: SET_COLLECTION( effect_control ); break;
         case PID_USAGE_SET_EFFECT_REPORT: SET_COLLECTION( effect_update ); break;
         case PID_USAGE_SET_PERIODIC_REPORT: SET_COLLECTION( set_periodic ); break;
+        case PID_USAGE_SET_ENVELOPE_REPORT: SET_COLLECTION( set_envelope ); break;
 
         case PID_USAGE_DEVICE_CONTROL: SET_SUB_COLLECTION( device_control, control_coll ); break;
         case PID_USAGE_EFFECT_OPERATION: SET_SUB_COLLECTION( effect_control, control_coll ); break;
@@ -1897,6 +1921,7 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap
     struct pid_control_report *effect_control = &impl->pid_effect_control;
     struct pid_effect_update *effect_update = &impl->pid_effect_update;
     struct pid_set_periodic *set_periodic = &impl->pid_set_periodic;
+    struct pid_set_envelope *set_envelope = &impl->pid_set_envelope;
 
     if (!(instance->dwType & DIDFT_OUTPUT)) return DIENUM_CONTINUE;
 
@@ -1975,6 +2000,26 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap
             set_periodic->offset_caps = caps;
         }
     }
+    if (instance->wCollectionNumber == set_envelope->collection)
+    {
+        SET_REPORT_ID( set_envelope );
+        if (instance->wUsage == PID_USAGE_ATTACK_LEVEL)
+        {
+            caps->physical_min = 0;
+            caps->physical_max = 10000;
+            set_envelope->attack_level_caps = caps;
+        }
+        if (instance->wUsage == PID_USAGE_ATTACK_TIME)
+            set_envelope->attack_time_caps = caps;
+        if (instance->wUsage == PID_USAGE_FADE_LEVEL)
+        {
+            caps->physical_min = 0;
+            caps->physical_max = 10000;
+            set_envelope->fade_level_caps = caps;
+        }
+        if (instance->wUsage == PID_USAGE_FADE_TIME)
+            set_envelope->fade_time_caps = caps;
+    }
 
 #undef SET_REPORT_ID
 
@@ -2082,12 +2127,19 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
     TRACE( "effect update id %u, coll %u, type_coll %u\n", impl->pid_effect_update.id,
            impl->pid_effect_update.collection, impl->pid_effect_update.type_coll );
     TRACE( "set periodic id %u, coll %u\n", impl->pid_set_periodic.id, impl->pid_set_periodic.collection );
+    TRACE( "set envelope id %u, coll %u\n", impl->pid_set_envelope.id, impl->pid_set_envelope.collection );
 
     if (impl->pid_device_control.id)
     {
         impl->dev_caps.dwFlags |= DIDC_FORCEFEEDBACK;
         if (impl->pid_effect_update.start_delay_caps)
             impl->dev_caps.dwFlags |= DIDC_STARTDELAY;
+        if (impl->pid_set_envelope.attack_level_caps ||
+            impl->pid_set_envelope.attack_time_caps)
+            impl->dev_caps.dwFlags |= DIDC_FFATTACK;
+        if (impl->pid_set_envelope.fade_level_caps ||
+            impl->pid_set_envelope.fade_time_caps)
+            impl->dev_caps.dwFlags |= DIDC_FFFADE;
         impl->dev_caps.dwFFSamplePeriod = 1000000;
         impl->dev_caps.dwFFMinTimeResolution = 1000000;
         impl->dev_caps.dwHardwareRevision = 1;
@@ -2171,6 +2223,7 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface )
         list_remove( &impl->entry );
         LeaveCriticalSection( &impl->joystick->base.crit );
         hid_joystick_private_decref( impl->joystick );
+        HeapFree( GetProcessHeap(), 0, impl->type_specific_buf[1] );
         HeapFree( GetProcessHeap(), 0, impl->type_specific_buf[0] );
         HeapFree( GetProcessHeap(), 0, impl->effect_update_buf );
         HeapFree( GetProcessHeap(), 0, impl->effect_control_buf );
@@ -2208,6 +2261,9 @@ static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface,
         status = HidP_InitializeReportForID( HidP_Output, joystick->pid_set_periodic.id,
                                              joystick->preparsed, impl->type_specific_buf[0], report_len );
         if (status != HIDP_STATUS_SUCCESS) return DIERR_DEVICENOTREG;
+        status = HidP_InitializeReportForID( HidP_Output, joystick->pid_set_envelope.id, joystick->preparsed,
+                                             impl->type_specific_buf[1], report_len );
+        if (status != HIDP_STATUS_SUCCESS) return DIERR_DEVICENOTREG;
         break;
     case PID_USAGE_ET_SPRING:
     case PID_USAGE_ET_DAMPER:
@@ -2218,6 +2274,7 @@ static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface,
     case PID_USAGE_ET_CUSTOM_FORCE_DATA:
         FIXME( "effect type %#x not implemented!\n", type );
         impl->type_specific_buf[0][0] = 0;
+        impl->type_specific_buf[1][0] = 0;
         break;
     }
 
@@ -2711,6 +2768,7 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface )
     struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
     struct pid_effect_update *effect_update = &impl->joystick->pid_effect_update;
     struct pid_set_periodic *set_periodic = &impl->joystick->pid_set_periodic;
+    struct pid_set_envelope *set_envelope = &impl->joystick->pid_set_envelope;
     ULONG report_len = impl->joystick->caps.OutputReportByteLength;
     HANDLE device = impl->joystick->device;
     struct hid_value_caps *caps;
@@ -2762,6 +2820,18 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface )
 
             if (WriteFile( device, impl->type_specific_buf[0], report_len, NULL, NULL )) hr = DI_OK;
             else hr = DIERR_INPUTLOST;
+
+            set_parameter_value( impl, impl->type_specific_buf[1], set_envelope->attack_level_caps,
+                                 impl->envelope.dwAttackLevel );
+            set_parameter_value_us( impl, impl->type_specific_buf[1], set_envelope->attack_time_caps,
+                                    impl->envelope.dwAttackTime );
+            set_parameter_value( impl, impl->type_specific_buf[1], set_envelope->fade_level_caps,
+                                 impl->envelope.dwFadeLevel );
+            set_parameter_value_us( impl, impl->type_specific_buf[1], set_envelope->fade_time_caps,
+                                    impl->envelope.dwFadeTime );
+
+            if (WriteFile( device, impl->type_specific_buf[1], report_len, NULL, NULL )) hr = DI_OK;
+            else hr = DIERR_INPUTLOST;
             break;
         }
 
@@ -2874,6 +2944,7 @@ static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirec
     if (!(impl->effect_control_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
     if (!(impl->effect_update_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
     if (!(impl->type_specific_buf[0] = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
+    if (!(impl->type_specific_buf[1] = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
 
     impl->envelope.dwSize = sizeof(DIENVELOPE);
     impl->params.dwSize = sizeof(DIEFFECT);
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 662953266ef..9c7a6ff7c1d 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5099,7 +5099,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
         /* set envelope */
         {
             .code = IOCTL_HID_WRITE_REPORT,
-            .todo = TRUE,
             .report_id = 6,
             .report_len = 7,
             .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
@@ -6555,7 +6554,6 @@ static void test_force_feedback_joystick( void )
     hr = IDirectInputDevice8_GetCapabilities( device, &caps );
     ok( hr == DI_OK, "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 );
-- 
2.33.0




More information about the wine-devel mailing list