Module: wine Branch: master Commit: b431dceeca9aa0d4229c3597b833bcaf04de7110 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b431dceeca9aa0d4229c3597b...
Author: Rémi Bernon rbernon@codeweavers.com Date: Thu Dec 2 10:47:43 2021 +0100
winebus.sys: Rotate directions to match the backend conventions.
The first direction in HID PID reports seems to be in polar space, rotated by 90° compared to the spherical coordinate space used in dinput. We need to fixup the directions to match Linux FF or SDL direction coordinate space.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51922 Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/winebus.sys/bus_sdl.c | 11 ++++++++--- dlls/winebus.sys/bus_udev.c | 11 +++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 003f6652f05..254971e1185 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -565,6 +565,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT struct sdl_device *impl = impl_from_unix_device(iface); int id = impl->effect_ids[index]; SDL_HapticEffect effect = {0}; + UINT16 direction; NTSTATUS status;
TRACE("iface %p, index %u, params %p.\n", iface, index, params); @@ -572,6 +573,10 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT if (params->effect_type == PID_USAGE_UNDEFINED) return STATUS_SUCCESS; if ((status = set_effect_type_from_usage(&effect, params->effect_type))) return status;
+ /* The first direction we get from PID is in polar coordinate space, so we need to + * remove 90° to make it match SDL spherical coordinates. */ + direction = (params->direction[0] - 9000) % 36000; + switch (params->effect_type) { case PID_USAGE_ET_SINE: @@ -584,7 +589,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.periodic.button = params->trigger_button; effect.periodic.interval = params->trigger_repeat_interval; effect.periodic.direction.type = SDL_HAPTIC_SPHERICAL; - effect.periodic.direction.dir[0] = params->direction[0]; + 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; @@ -605,7 +610,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.condition.button = params->trigger_button; effect.condition.interval = params->trigger_repeat_interval; effect.condition.direction.type = SDL_HAPTIC_SPHERICAL; - effect.condition.direction.dir[0] = params->direction[0]; + effect.condition.direction.dir[0] = direction; effect.condition.direction.dir[1] = params->direction[1]; if (params->condition_count >= 1) { @@ -633,7 +638,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.constant.button = params->trigger_button; effect.constant.interval = params->trigger_repeat_interval; effect.constant.direction.type = SDL_HAPTIC_SPHERICAL; - effect.constant.direction.dir[0] = params->direction[0]; + effect.constant.direction.dir[0] = direction; effect.constant.direction.dir[1] = params->direction[1]; effect.constant.level = params->constant_force.magnitude; effect.constant.attack_length = params->envelope.attack_time; diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 521ae4192b5..2ec15ecb6ad 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1031,8 +1031,15 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B effect.replay.delay = params->start_delay; effect.trigger.button = params->trigger_button; effect.trigger.interval = params->trigger_repeat_interval; - /* only supports polar with one direction angle */ - effect.direction = params->direction[0] * 0x800 / 1125; + + /* Linux FF only supports polar direction, and uses an inverted convention compared + * to SDL or dinput (see SDL src/haptic/linux/SDL_syshaptic.c), where the force pulls + * into the specified direction, instead of coming from it. + * + * The first direction we get from PID is in polar coordinate space, so we need to + * add 180° to make it match Linux coordinates. */ + effect.direction = (params->direction[0] + 18000) % 36000; + effect.direction = effect.direction * 0x800 / 1125;
switch (params->effect_type) {