https://bugs.winehq.org/show_bug.cgi?id=51922
Bug ID: 51922 Summary: Xinput Joystick backend broke Force Feedback in Starlancer Product: Wine Version: 6.20 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: xinput Assignee: wine-bugs@winehq.org Reporter: jcarthew@gmail.com Distribution: ---
Recent Joystick backend updates added in WINE 6.20 have broken Force Feedback support in Microsoft StarLancer. Have tested with a Microsoft SideWinder Force Feedback 2. Joystick has Force Feedback in Control Panel but no longer has Force Feedback in game. This has been working in WINE for the past ~10 years.
https://bugs.winehq.org/show_bug.cgi?id=51922
Rémi Bernon rbernon@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |rbernon@codeweavers.com
--- Comment #1 from Rémi Bernon rbernon@codeweavers.com --- Thanks for the report, I've very possible that the changes have caused some regressions.
If you could provide the output of Wine when running the game with WINEDEBUG=+dinput,+xinput,+winexinput,+plugplay,+hid,+hidp,+hid_report environment variable that would be extremely helpful to debug the problem.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #2 from James Carthew jcarthew@gmail.com --- I've generated the log but it's 78MB. Where can I dump it?
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #3 from James Carthew jcarthew@gmail.com --- Created attachment 70886 --> https://bugs.winehq.org/attachment.cgi?id=70886 Trace of debug output from xinput.
Attached 7zip compressed joystick Trace.
https://bugs.winehq.org/show_bug.cgi?id=51922
Rémi Bernon rbernon@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|xinput |directx-dinput
--- Comment #4 from Rémi Bernon rbernon@codeweavers.com --- I can reproduce some issues with a standard gamepad, where rumble effects (when hitting another spaceship for instance) are delayed, but I'm not sure if it's the same thing you are experiencing.
(This problem comes from the game specifying a start delay effect parameter, which is unexpectedly large. Probably we could ignore it or its semantic is different from what we expect.)
What kind of force feedback effects were you expecting? If I upload some patches are you able to build wine to try them out?
Also, are you able to produce the same kind of log with a older version of Wine where everything is fine?
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #5 from James Carthew jcarthew@gmail.com --- Yes I can provide a trace from an older WINE version. I'm expecting full recoil effects when the guns are fired, as well as rumble/vibration effects when I hit the afterburners.
https://bugs.winehq.org/show_bug.cgi?id=51922
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |hardware
https://bugs.winehq.org/show_bug.cgi?id=51922
Citrodata citrodata@gmx.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |citrodata@gmx.de
--- Comment #6 from Citrodata citrodata@gmx.de --- I can confirm that Force Feedback isn't working for my two Racing Wheels (Driving Force GT and T150). Both work fine with Wine 6.19 but with 6.20 and 6.21 Force Feedback is broken in every game I tested (Assetto Corsa, Assetto Corsa Competizion, BeamNG, Rfactor 2).
https://bugs.winehq.org/show_bug.cgi?id=51922
jonathon@m2x.dev changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jonathon@m2x.dev
--- Comment #7 from jonathon@m2x.dev --- (In reply to Citrodata from comment #6)
I can confirm that Force Feedback isn't working for my two Racing Wheels (Driving Force GT and T150). Both work fine with Wine 6.19 but with 6.20 and 6.21 Force Feedback is broken in every game I tested (Assetto Corsa, Assetto Corsa Competizion, BeamNG, Rfactor 2).
Also confirming my G29 lost FFB with 6.20; works fine with 6.19.
https://bugs.winehq.org/show_bug.cgi?id=51922
Rémi Bernon rbernon@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Xinput Joystick backend |HID joystick constant Force |broke Force Feedback in |Feedback effect does not |Starlancer |work
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #8 from Rémi Bernon rbernon@codeweavers.com --- The start delay problem with StarLancer is something that I believe was already there before. The game doesn't set any value to the dwStartDelay field, although it sets the structure size to include it.
The value is whatever remains on the stack, so if the behavior changed maybe it's because we didn't respect the delay before and we do now, but as far as I can see it's working as expected. The only possible workaround I can think of is to ignore delay values that are unexpectedly large, although that's not correct.
In any case I could not get any effect to be requested when firing weapons or using afterburners, is there anything specific to do?
Regarding broken force-feedback with other devices and other games, I could see some failures when creating the effects, and I have some patches which should hopefully fix these.
https://bugs.winehq.org/show_bug.cgi?id=51922
Julian Rüger jr98@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jr98@gmx.net
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #9 from Rémi Bernon rbernon@codeweavers.com --- Would you mind trying again with Wine 6.22? There's been a substantial amount of related fixes, and I have some hopes that most issues should be resolved now.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #10 from Citrodata citrodata@gmx.de --- (In reply to Rémi Bernon from comment #9)
Would you mind trying again with Wine 6.22? There's been a substantial amount of related fixes, and I have some hopes that most issues should be resolved now.
Force Feedback works a little bit. You can feel that the Games send Force Feedback Data to the Wheel but the effects are all wrong and doesn't work correctly. When driving on gravel or sand nothing is send to the wheel. And everything else feels like its not enough force or the effects are inverted. Tested with Assetto Corsa, Beam NG and WRC 8. All work fine with both Wheels I have with Wine 6.19.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #11 from Rémi Bernon rbernon@codeweavers.com --- Thanks, I believe I finally found the problem. Looks like evdev force feedback directions use a different convention from DInput or HID PID (and SDL does as well), I'll send some patches that should address this today.
https://bugs.winehq.org/show_bug.cgi?id=51922
Ivo Ivanov logos128@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |logos128@gmail.com
--- Comment #12 from Ivo Ivanov logos128@gmail.com --- I can confirm that the SDL backend now works properly regarding the direction of the effect. Tested it with Automobilista 2 and WheelCheck. Both use direction 0x2d for the first axis (X), equal to hidraw and Windows. Subjectively the FFB felt the same like Windows (with Simucube 2 Sport).
The UDEV lnxev also works now. Although the FFB is smoother and weaker, similar to the SDL before. And probably it's caused by the direction, which is 0x87 while on Windows and hidraw it is 0x2d. Tested it only with WheelCheck, though.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #13 from Rémi Bernon rbernon@codeweavers.com --- Okay, maybe I just got confused with all the conversions.
I did some tests with BeamNG, checking what we were previously passing to the legacy dinput Linux evdev backend, and making sure winebus.sys is doing the same.
In my test the game used a 1 axis effect with a single -1 direction set to cartesian coordinate. As it's just 1 axis, the direction doesn't have any effect here, and the default direction is used, which is 0 in spherical coordinates or 90° in polar (force coming from the east or user's right).
This was previously converted to a Linux evdev direction of 0xc000, which if I understand correctly what SDL source describes, is a force "pulling into the 270° direction", so pulling into west or user's left.
With the new driver this gets written to Wine PID reports as a single 9000 (0x2328) direction value, which should be visible on the +hid debug channel. And I changed the evdev backend to map it to 0xc000, like we were doing before, and this seemed to match some comment in SDL code too [1].
Then I haven't checked how this gets translated again by the Linux evdev driver down to Linux kernel HID reports, maybe it just passes it unmodified and there's some different expectations between devices?
[1] That part of https://github.com/libsdl-org/SDL/blob/main/src/haptic/linux/SDL_syshaptic.c... is a bit confusing though, as the SDL_HAPTIC_SPHERICAL case seems to do a simple direct mapping, unless SDL_HAPTIC_SPHERICAL and SDL_HAPTIC_POLAR are inverted but I don't see any clue that they are. Maybe it's all wrong and maybe we should not change the coordinates at all for evdev.
Would you mind checking if reverting the lnxev_device_physical_effect_update change in b431dceeca9aa0d4229c3597b833bcaf04de7110 makes it correct now?
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #14 from Ivo Ivanov logos128@gmail.com --- Created attachment 71221 --> https://bugs.winehq.org/attachment.cgi?id=71221 winebus-fixes.patch
I remember that comment in the SDL code :) I got confused by it when I was writing a Linux FFB driver for a Fanatec device and found it on the net. Maybe they mean the 90 deg difference between polar and spherical. Anyway, it is visible from the SDL code that they just rescale the source polar coords to the Linux FF range.
So your previous code was correct. I have reverted the lnxev part of the patch, and immediately the "set effect" output reports started showing the correct direction 0x2d similar to the other backends and Windows.
The FFB was still absent, though, so I looked at some captured usb traffic, and found two interesting things. The FF gain was set to 0 on the lnxev backend, and the duration field of the "set effect" report was 0x7fff on the both SDL and lnxev backends.
For the first issue appeared that FF_GAIN needed to be rescaled for the Linux FF range.
For the second issue, we pass correctly 0xffff for infinite duration, but Linux just clamps it to the max allowed value of 0x7fff, as it doesn't consider that value an infinite duration. The Linux FF uses 0 for that, while SDL uses SDL_HAPTIC_INFINITY.
So, attached patches that correct the issues. Tested thoroughly both the SDL and lnxev backends with various games - rFactor 2, Assetto Corsa Competizione, Automobilista 2, BeamNG, etc. The FFB worked properly and on par with hidraw and Windows. The only problem I could still spot is that the damper condition effect is very weak in comparison to hidraw and Windows. Assetto Corsa Competizione uses such effect when the car is stand still.
The patches are based on 3f6102080e632b9f4d8a97c0f0b1231fbd8e759b
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #15 from Rémi Bernon rbernon@codeweavers.com --- (In reply to Ivo Ivanov from comment #14)
Created attachment 71221 [details] winebus-fixes.patch
I remember that comment in the SDL code :) I got confused by it when I was writing a Linux FFB driver for a Fanatec device and found it on the net. Maybe they mean the 90 deg difference between polar and spherical. Anyway, it is visible from the SDL code that they just rescale the source polar coords to the Linux FF range.
You're right, I've been so much confused by the comment that I even read the code as if it was actually doing what it described, but it isn't...
So your previous code was correct. I have reverted the lnxev part of the patch, and immediately the "set effect" output reports started showing the correct direction 0x2d similar to the other backends and Windows.
What I'm still puzzled with is that the legacy dinput evdev backend we previously had was using the same direction rotations as we are now. I wouldn't trust it too much though, it's possible that it also got it wrong, or that the inversion was indeed here in the Linux kernel, a long time ago.
The FFB was still absent, though, so I looked at some captured usb traffic, and found two interesting things. The FF gain was set to 0 on the lnxev backend, and the duration field of the "set effect" report was 0x7fff on the both SDL and lnxev backends.
For the first issue appeared that FF_GAIN needed to be rescaled for the Linux FF range.
For the second issue, we pass correctly 0xffff for infinite duration, but Linux just clamps it to the max allowed value of 0x7fff, as it doesn't consider that value an infinite duration. The Linux FF uses 0 for that, while SDL uses SDL_HAPTIC_INFINITY.
So, attached patches that correct the issues. Tested thoroughly both the SDL and lnxev backends with various games - rFactor 2, Assetto Corsa Competizione, Automobilista 2, BeamNG, etc. The FFB worked properly and on par with hidraw and Windows. The only problem I could still spot is that the damper condition effect is very weak in comparison to hidraw and Windows. Assetto Corsa Competizione uses such effect when the car is stand still.
The patches are based on 3f6102080e632b9f4d8a97c0f0b1231fbd8e759b
Thanks for the fixes, they look right indeed.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #16 from Rémi Bernon rbernon@codeweavers.com --- (In reply to Ivo Ivanov from comment #14)
The only problem I could still spot is that the damper condition effect is very weak in comparison to hidraw and Windows. Assetto Corsa Competizione uses such effect when the car is stand still.
Could it be that the saturations and deadband values are scaled to 0-0x7fff, although they are unsigned and should maybe use an 0-0xffff range?
Something like this maybe:
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 8680f8a088c..32628f1f2fd 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -641,7 +641,7 @@ static BOOL hid_descriptor_add_set_condition(struct unix_device *iface) USAGE(1, PID_USAGE_NEGATIVE_SATURATION), USAGE(1, PID_USAGE_DEAD_BAND), LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(2, 0x7fff), + LOGICAL_MAXIMUM(4, 0xffff), PHYSICAL_MINIMUM(1, 0), PHYSICAL_MAXIMUM(2, +10000), REPORT_SIZE(1, 16),
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #17 from Ivo Ivanov logos128@gmail.com --- The SDL_haptic.h header specifies the ranges of those three values as 0..0xffff, so this seems correct. I tested Assetto Corsa Competizione with this patch, but it still doesn't have damping effect on stand still (in both lnxev and sdl).
So, I've captured some usb traffic from the three backends, and will analyze it later. At first glance both sdl and lnxev send two condition reports for the two axes that are required/supported by these APIs. The second one is with null values. I wonder why the Linux PID driver is not filtering the second one, though, since the device declares a single axis (X) in its descriptor. Maybe they don't analyze the reports at such level.
The hidraw backend sends a single condition report with values different than the other two backends. Will see what is different, and will let you know.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #18 from Rémi Bernon rbernon@codeweavers.com --- Thanks, as far as I could see in the hid-pidff Linux driver, they always send the two condition reports, regardless of their value. From the DInput MSDN documentation, it is mentioned that when only one condition is set, it's supposed to be used for all axes (with supposedly the direction applied to modulate the effect, but I didn't find any clue that it's true).
Maybe what we need to do for the SDL and evdev backends is to copy the first condition onto the second one when there's only one, so that the underlying drivers never send empty conditions.
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #19 from Ivo Ivanov logos128@gmail.com --- Created attachment 71247 --> https://bugs.winehq.org/attachment.cgi?id=71247 0001-dinput-Add-condition-parameters-for-all-declared-axi.patch
(In reply to Rémi Bernon from comment #18)
Thanks, as far as I could see in the hid-pidff Linux driver, they always send the two condition reports, regardless of their value.
Yes, it seems the hid-pidff driver is causing this. They don't check the number of the declared axes in the set effect report. Just always send two condition reports, which the device interprets as two consequential reports, without ever checking the block offset field. And since the second report is always with null values, it just turns off the effect.
From the DInput MSDN documentation, it is mentioned that when only one condition is set, it's supposed to be used for all axes (with supposedly the direction applied to modulate the effect, but I didn't find any clue that it's true).
According to the HID PID specification if Direction Enable is used in the Set Effect report, the Axes Enable flags are ignored and only one Condition report is defined with the Direction (from Set Effect) applied as a polar direction. I think there is an example in MSDN, about the polar direction used in this case, and maybe also some additional info in the specification.
Maybe what we need to do for the SDL and evdev backends is to copy the first condition onto the second one when there's only one, so that the underlying drivers never send empty conditions.
You are absolutely right! I have found some old usb captures from proton's joystick_sdl, and they seem to fill exactly the same values for the second one as the first. This results in two identical condition reports with consequential parameter offset fields from the driver. I have tested this technique, and indeed the condition effects function properly.
Attached a patch for this, although didn't test it too much. Captured the usb traffic and noted that the pairs sometimes have different coefficient fields. Maybe since I implemented it in dinput/joystick_hid and a better place to implement it would be in the backends (probably more difficult, though).
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #20 from Citrodata citrodata@gmx.de --- So i tested everything now with Wine Version 7.0.0rc2 with both Wheels. Both times Force Feedback felt as good as with version 6.19.
https://bugs.winehq.org/show_bug.cgi?id=51922
mirh mirh@protonmail.ch changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |mirh@protonmail.ch
--- Comment #21 from mirh mirh@protonmail.ch --- There's seems to be a bit of a kernel conundrum here gentlemen. https://patches.linaro.org/project/linux-usb/patch/20221001221657.gexisc2egj... https://lore.kernel.org/lkml/20240521220719.niwhskc473he5r5o@zitz/T/
https://bugs.winehq.org/show_bug.cgi?id=51922
--- Comment #22 from Ivo Ivanov logos128@gmail.com --- (In reply to mirh from comment #21)
There's seems to be a bit of a kernel conundrum here gentlemen.
Interesting. It seems that some devices like Accuforce don't interpret 0 as an 'infinite' value. I have a SimuCube 2 which works properly with 0 for replay length. If we set this to 0xffff, though, it may cause issues with some of the ff-memless devices, as mentioned in the linux kernel discussion. IMO let's wait for the kernel devs to handle this properly.
Anyway, the hidraw backend (winebus.sys) is preferred for use with such devices in Wine, as it enables Windows apps to access the device directly through HidD/HidP calls. This would allow advanced features like setting "end of rotation bumpstops" or even sending additional ffb effects, as the Accuforce app does IIRC. It also solves the above issue.