From: Tomasz Pakuła tomasz.pakula.oficjalny@gmail.com
FFB Autocenter introduced in https://gitlab.winehq.org/wine/wine/-/merge_requests/4911 had one major misunderstanding.
The USB PID standard doesn't actually define any explicit way to autocenter a device. One could of course use the spring effect with a deadzone of 0 and dead band of 0. This is what I'm actually working on for the Linux PID driver (spring + friction/damper).
Some devices implement autocenter in firmware when they receive the DC Disable Actuators command. Very few, if not just one, implement this weird autocenter effect on slot 1. This is, from what I can gather, only implemented on the MS SideWinder joystick(s) and the Windows' USB PID driver is created around these devices.
Windows PID driver is a bit out of spec, is quite permissive when it comes to fields missing in the descriptor (basically, only effect types and their effect type blocks are optional). Another thing it does is handling of this out-of-spec autocentering for their joysticks. Funnliy enough, the creator of the Linux PID driver based the initial code on testing with MS Sidewinder so it's autocentering is supported.
This is where the autocentering mentioned in the MR comes from. It's not the directinput api that does it but the Windows PID driver. As such, autocentering on reset should be left to the drivers, not handeled by Wine.
SDL lacks full reset support and Linux is even more barebones, whre it's not even possible to query the device state, effects etc (something I'm working on slowly). As such, when games send out RESET to prepare the device, the device starts autocentering for no good reason and the effect is not removed once other effect are uploaded and played which would be the case for MS sidewinder.
tl;dr Set autocentering to 0 instead of max value when DISFFC_RESET is reveived to remove the unwanted autocenter behavior.
Signed-off-by: Tomasz Pakuła tomasz.pakula.oficjalny@gmail.com --- dlls/winebus.sys/bus_sdl.c | 2 +- dlls/winebus.sys/bus_udev.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 5cec049a845..318a0b8c6e5 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -560,7 +560,7 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US pSDL_HapticDestroyEffect(impl->sdl_haptic, impl->effect_ids[i]); impl->effect_ids[i] = -1; } - pSDL_HapticSetAutocenter(impl->sdl_haptic, 100); + pSDL_HapticSetAutocenter(impl->sdl_haptic, 0); return STATUS_SUCCESS; case PID_USAGE_DC_DEVICE_PAUSE: pSDL_HapticPause(impl->sdl_haptic); diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 39b810b7588..d660da71644 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -921,7 +921,7 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, WARN("couldn't free effect, EVIOCRMFF ioctl failed: %d %s\n", errno, strerror(errno)); impl->effect_ids[i] = -1; } - lnxev_device_physical_device_set_autocenter(iface, 100); + lnxev_device_physical_device_set_autocenter(iface, 0); return STATUS_SUCCESS; case PID_USAGE_DC_DEVICE_PAUSE: WARN("device pause not supported\n");