From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 8 ++++---- dlls/winebus.sys/bus_udev.c | 8 ++++---- dlls/winebus.sys/hid.c | 9 +++++++++ dlls/winebus.sys/unix_private.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index a1e7942fe59..a5621972493 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -647,7 +647,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.periodic.direction.dir[0] = direction; effect.periodic.direction.dir[1] = params->direction[1]; effect.periodic.period = params->periodic.period; - effect.periodic.magnitude = params->periodic.magnitude; + effect.periodic.magnitude = (params->periodic.magnitude * params->gain_percent) / 100; effect.periodic.offset = params->periodic.offset; effect.periodic.phase = params->periodic.phase; effect.periodic.attack_length = params->envelope.attack_time; @@ -695,7 +695,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.constant.direction.type = SDL_HAPTIC_SPHERICAL; effect.constant.direction.dir[0] = direction; effect.constant.direction.dir[1] = params->direction[1]; - effect.constant.level = params->constant_force.magnitude; + effect.constant.level = (params->constant_force.magnitude * params->gain_percent) / 100; effect.constant.attack_length = params->envelope.attack_time; effect.constant.attack_level = params->envelope.attack_level; effect.constant.fade_length = params->envelope.fade_time; @@ -712,8 +712,8 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.ramp.direction.type = SDL_HAPTIC_SPHERICAL; effect.ramp.direction.dir[0] = params->direction[0]; effect.ramp.direction.dir[1] = params->direction[1]; - effect.ramp.start = params->ramp_force.ramp_start; - effect.ramp.end = params->ramp_force.ramp_end; + effect.ramp.start = (params->ramp_force.ramp_start * params->gain_percent) / 100; + effect.ramp.end = (params->ramp_force.ramp_end * params->gain_percent) / 100; effect.ramp.attack_length = params->envelope.attack_time; effect.ramp.attack_level = params->envelope.attack_level; effect.ramp.fade_length = params->envelope.fade_time; diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 39573162afa..21a70d0829b 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1138,7 +1138,7 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B case PID_USAGE_ET_SAWTOOTH_UP: case PID_USAGE_ET_SAWTOOTH_DOWN: effect.u.periodic.period = params->periodic.period; - effect.u.periodic.magnitude = params->periodic.magnitude; + effect.u.periodic.magnitude = (params->periodic.magnitude * params->gain_percent) / 100; effect.u.periodic.offset = params->periodic.offset; effect.u.periodic.phase = params->periodic.phase * 0x800 / 1125; effect.u.periodic.envelope.attack_length = params->envelope.attack_time; @@ -1172,7 +1172,7 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B break;
case PID_USAGE_ET_CONSTANT_FORCE: - effect.u.constant.level = params->constant_force.magnitude; + effect.u.constant.level = (params->constant_force.magnitude * params->gain_percent) / 100; effect.u.constant.envelope.attack_length = params->envelope.attack_time; effect.u.constant.envelope.attack_level = params->envelope.attack_level; effect.u.constant.envelope.fade_length = params->envelope.fade_time; @@ -1180,8 +1180,8 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B break;
case PID_USAGE_ET_RAMP: - effect.u.ramp.start_level = params->ramp_force.ramp_start; - effect.u.ramp.end_level = params->ramp_force.ramp_end; + effect.u.ramp.start_level = (params->ramp_force.ramp_start * params->gain_percent) / 100; + effect.u.ramp.end_level = (params->ramp_force.ramp_end * params->gain_percent) / 100; effect.u.ramp.envelope.attack_length = params->envelope.attack_time; effect.u.ramp.envelope.attack_level = params->envelope.attack_level; effect.u.ramp.envelope.fade_length = params->envelope.fade_time; diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index de0c3bb0848..8ed8c752893 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -487,6 +487,7 @@ struct pid_effect_update UINT16 trigger_repeat_interval; UINT16 sample_period; UINT16 start_delay; + BYTE gain_percent; BYTE trigger_button; BYTE enable_bits; UINT16 direction[2]; @@ -909,6 +910,13 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co UNIT_EXPONENT(1, 0), UNIT(1, 0), /* None */
+ USAGE(1, PID_USAGE_GAIN), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 100), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs|Null), + USAGE(1, PID_USAGE_TRIGGER_BUTTON), LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, state->button_count), @@ -1181,6 +1189,7 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC params->trigger_repeat_interval = report->trigger_repeat_interval; params->sample_period = report->sample_period; params->start_delay = report->start_delay; + params->gain_percent = report->gain_percent; params->trigger_button = report->trigger_button == 0xff ? 0 : report->trigger_button; params->axis_enabled[0] = (report->enable_bits & 1) != 0; params->axis_enabled[1] = (report->enable_bits & 2) != 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index ab8060611a4..f94a243d887 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -78,6 +78,7 @@ struct effect_params BOOL axis_enabled[2]; BOOL direction_enabled; UINT16 direction[2]; + BYTE gain_percent; BYTE condition_count; /* only for periodic, constant or ramp forces */ struct effect_envelope envelope;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/force_feedback.c | 18 ---------------- dlls/windows.gaming.input/force_feedback.c | 25 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index c471a80de00..182bb9919bb 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -5596,7 +5596,6 @@ static void test_windows_gaming_input(void) .report_id = 2, .report_len = 4, .report_buf = {2,0x01,0x01,0x01}, - .todo = TRUE, }; struct hid_expect expect_effect_stop = { @@ -5604,7 +5603,6 @@ static void test_windows_gaming_input(void) .report_id = 2, .report_len = 4, .report_buf = {2,0x01,0x03,0x00}, - .todo = TRUE, }; struct hid_expect expect_unload[] = { @@ -6103,20 +6101,16 @@ static void test_windows_gaming_input(void)
set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr );
set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr );
set_hid_expect( file, expect_unload, sizeof(expect_unload) ); @@ -6200,20 +6194,16 @@ static void test_windows_gaming_input(void)
set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr );
set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr );
set_hid_expect( file, expect_unload, sizeof(expect_unload) ); @@ -6299,20 +6289,16 @@ static void test_windows_gaming_input(void)
set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr );
set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr );
set_hid_expect( file, expect_unload, sizeof(expect_unload) ); @@ -6377,20 +6363,16 @@ static void test_windows_gaming_input(void)
set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_start, sizeof(expect_effect_start) ); hr = IForceFeedbackEffect_Start( effect ); - todo_wine ok( hr == S_OK, "Start returned %#lx\n", hr );
set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr ); set_hid_expect( file, &expect_effect_stop, sizeof(expect_effect_stop) ); hr = IForceFeedbackEffect_Stop( effect ); - todo_wine ok( hr == S_OK, "Stop returned %#lx\n", hr );
set_hid_expect( file, expect_unload, sizeof(expect_unload) ); diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index dd10f86bd3e..51d02171001 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -242,14 +242,31 @@ static HRESULT WINAPI effect_get_State( IForceFeedbackEffect *iface, ForceFeedba
static HRESULT WINAPI effect_Start( IForceFeedbackEffect *iface ) { - FIXME( "iface %p stub!\n", iface ); - return E_NOTIMPL; + struct effect *impl = impl_from_IForceFeedbackEffect( iface ); + HRESULT hr = E_UNEXPECTED; + DWORD flags = 0; + + TRACE( "iface %p.\n", iface ); + + EnterCriticalSection( &impl->cs ); + if (impl->effect) hr = IDirectInputEffect_Start( impl->effect, impl->repeat_count, flags ); + LeaveCriticalSection( &impl->cs ); + + return hr; }
static HRESULT WINAPI effect_Stop( IForceFeedbackEffect *iface ) { - FIXME( "iface %p stub!\n", iface ); - return E_NOTIMPL; + struct effect *impl = impl_from_IForceFeedbackEffect( iface ); + HRESULT hr = E_UNEXPECTED; + + TRACE( "iface %p.\n", iface ); + + EnterCriticalSection( &impl->cs ); + if (impl->effect) hr = IDirectInputEffect_Stop( impl->effect ); + LeaveCriticalSection( &impl->cs ); + + return hr; }
static const struct IForceFeedbackEffectVtbl effect_vtbl =
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/force_feedback.c | 4 ---- dlls/windows.gaming.input/force_feedback.c | 21 +++++++++++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index 182bb9919bb..c7498e45727 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -6020,9 +6020,7 @@ static void test_windows_gaming_input(void) ok( hr == S_FALSE, "put_Gain returned %#lx\n", hr ); state = 0xdeadbeef; hr = IForceFeedbackEffect_get_State( effect, &state ); - todo_wine ok( hr == S_OK, "get_State returned %#lx\n", hr ); - todo_wine ok( state == ForceFeedbackEffectState_Stopped, "got state %#x\n", state ); hr = IForceFeedbackEffect_Start( effect ); todo_wine @@ -6260,9 +6258,7 @@ static void test_windows_gaming_input(void) ok( hr == S_FALSE, "put_Gain returned %#lx\n", hr ); state = 0xdeadbeef; hr = IForceFeedbackEffect_get_State( effect, &state ); - todo_wine ok( hr == S_OK, "get_State returned %#lx\n", hr ); - todo_wine ok( state == ForceFeedbackEffectState_Stopped, "get_State returned %#lx\n", hr ); hr = IForceFeedbackEffect_Start( effect ); todo_wine diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index 51d02171001..198268eac24 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -236,8 +236,25 @@ static HRESULT WINAPI effect_put_Gain( IForceFeedbackEffect *iface, DOUBLE value
static HRESULT WINAPI effect_get_State( IForceFeedbackEffect *iface, ForceFeedbackEffectState *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct effect *impl = impl_from_IForceFeedbackEffect( iface ); + DWORD status; + HRESULT hr; + + TRACE( "iface %p, value %p.\n", iface, value ); + + EnterCriticalSection( &impl->cs ); + if (!impl->effect) + *value = ForceFeedbackEffectState_Stopped; + else if (FAILED(hr = IDirectInputEffect_GetEffectStatus( impl->effect, &status ))) + *value = ForceFeedbackEffectState_Faulted; + else + { + if (status == DIEGES_PLAYING) *value = ForceFeedbackEffectState_Running; + else *value = ForceFeedbackEffectState_Stopped; + } + LeaveCriticalSection( &impl->cs ); + + return S_OK; }
static HRESULT WINAPI effect_Start( IForceFeedbackEffect *iface )
From: Rémi Bernon rbernon@codeweavers.com
We will get hotplug notifications asynchronously, and returning an error here can cause uncaught C++ exceptions in games.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c index 1f3f4e047f5..39229a35c7d 100644 --- a/dlls/windows.gaming.input/provider.c +++ b/dlls/windows.gaming.input/provider.c @@ -212,7 +212,7 @@ static HRESULT WINAPI wine_provider_get_State( IWineGameControllerProvider *ifac if (FAILED(hr = IDirectInputDevice8_GetDeviceState( impl->dinput_device, sizeof(state), &state ))) { WARN( "Failed to read device state, hr %#lx\n", hr ); - return hr; + return S_OK; }
i = ARRAY_SIZE(state.rgbButtons);