Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Length 0 instead of 0xFFFF for infinite effect duration. #26

Open
groybe opened this issue Mar 17, 2022 · 36 comments
Open

Length 0 instead of 0xFFFF for infinite effect duration. #26

groybe opened this issue Mar 17, 2022 · 36 comments
Labels
question Further information is requested

Comments

@groybe
Copy link

groybe commented Mar 17, 2022

Name of the game: Fedit
Steam ID: No Steam
Game version: 1.0
Game Type (native/proton/wine): Wine
Proton/Wine version: wine-7.2 (Staging)
Wheel Model: OpenFFBoard (https://github.com/Ultrawipf/OpenFFBoard)
Compatibility Mode: None
Distribution: Fedora 34
Kernel version: 5.16.12-100

Force Feedback present: No
Symptoms or Special Notes: Fedit (also I tried Richard Burns Rally) My wheel recieves length as 0 instead of 0xFFFF for infinite effect duration.

I used rohitab api monitor to confirm that dinput out of fedit sends 0xFFFF so I guess this might not be a wine issue.
At this point I'm lost. Can anyone point me where to look next?

Native program Tux racer appears to work although only in one direction but I think that's a whole other issue.

The creator of OpenFFboard has confirmed it arrives at the OpenFFBoard itself as 0xFFFF on a windows machine. They seem to think it is a linux issue.
My G25 wheel gets sent 0 as length but seems to just accept this and play the effect anyways.
Should the openFFBoard handle this the same way? I'm not sure this would be to standards?

The log on wine staging is empty for some reason. But the wrapper is working. I've added a length overwrite here and it works.

Log from wine lutris-5.7-11-x86_64
000034473776 > UPLOAD id:2 dir:15681 length:0 delay:0 type:CONSTANT level:-8192 attack_length:0 attack_level:32000 fade_length:0 fade_level:32000

Thanks for anyone who takes the time to look at this.

@berarma
Copy link
Owner

berarma commented Mar 17, 2022

The Linux FF API is different to Windows. The Linux source code has this comment:

All duration values are expressed in ms. Values above 32767 ms (0x7fff) should not be used and have unspecified results.

So using 0xFFFF can give unexpected results, it could even work but it's not following the API specs.

Infinite effect duration is requested with replay.length = 0.

Proton 7.0 has switched to a new input API implementation and has issues with wheels and FF. Wine might have similar issues in case they've switched to this new implementation.

@groybe
Copy link
Author

groybe commented Mar 18, 2022

Thanks for the quick response.
Ah that might ruin the author of OpenFFBoard's plans for compatibility of universal drivers across windows and linux.

Anyways I have a dirty fix using your wrapper here. https://github.com/groybe/ffbtools/tree/OpenFFBoard_fix

Thanks again!

@Ultrawipf
Copy link

Ultrawipf commented Mar 18, 2022

I changed the behaviour in the OpenFFBoard firmware back to treating 0xffff and 0 as infinite. The PID standard is not fully clear about if the maximum or 0 is treated as infinite. Check the definitions page of the PID document. That indicates to me that it is likely the max value.
Never seen anything on windows send 0. Windows always uses the maximum but also no game would send 0 it seems so its probably best to treat both as infinite for compatibility reasons.

But there are currently other issues. I can't get FFB at all to work on my linux machine at the moment to test it.

Maybe someone here has an idea.
dmesg always reports implement() called with too large value 4 (n: 1)! which hints at core-hid.c and sometimes when an effect should be loaded it reports upload request failed.

device reports 0 simultaneous effects
pid_block_load failed 60 times
upload request failed

But the device never receives an effect request at all for some reason so it could be a descriptor interpretation problem on linux.
Linux seems very strict about what fields must be present in the descriptor in what order with which values while on windows the descriptor defines what capabilities the device has and the OS sends reports accordingly.

@berarma
Copy link
Owner

berarma commented Mar 18, 2022

Hi @Ultrawipf. I was following your work some time ago. I'm glad you're still working on it. It's very interesting and I hope I can get to try it sometime and perhaps help.

I didn't know about the PID document, it isn't in the usb.org index of documents. Logitech wheels don't use it and I don't know any wheels using it. In any case, that's for the USB interface, we're comparing the Windows and Linux interfaces, at a higher level of abstraction.

The PID document is fundamentally done by Microsoft so it may have similarities with DInput on Windows.

I haven't found any Linux documentation that says 0 is infinite duration but it's implied by drivers and Wine. Search "infinite" in this discussion in the Wine mailing list.

About the other issues, I don't know how you are interfacing with the OpenFFBoard firmware. I guess you would need a driver or use hidraw. Maybe I don't know enough about USB and its implementation on Linux, though.

@Ultrawipf
Copy link

Currently debugging the linux handling of the device memory management reports.
It seems like windows does not really care about those reports while on linux it is quite important.
There was indeed a bug in the pool and block load report replies causing a 1 byte offset causing it not to detect the device managed memory flag (if it is not 1 hid-pidff.c seems to fail immediately).
The device is now detected again and effects can be sent but there are still some things to fix.

Also the "autocentering detection" is a bit weird causing some workarounds for other games to break again. Not sure if it was ever common to have a preset spring effect for autocentering. Never seen that before.

If you have some sources to look into about the lower level device management (pool report, block load report, effect creation sequences on linux) it would be nice to look into. The effect setup sequencing does not follow the windows order so thats something i need to look into for now.

@Ultrawipf
Copy link

The Linux FF API is different to Windows. The Linux source code has this comment:

All duration values are expressed in ms. Values above 32767 ms (0x7fff) should not be used and have unspecified results.

So using 0xFFFF can give unexpected results, it could even work but it's not following the API specs.

I checked again and indeed in our firmware the maximum valid range is until 0x7fff but windows will send 0xffff as infinite.
According to the PID document the "maximum of a range" is infinite so for a 16b value that might actually be 0xffff here and not the maximum of the defined valid range of a value which is 0x7fff then.

@berarma
Copy link
Owner

berarma commented Apr 25, 2022

The differences between OS level APIs and firmware APIs should be handled by drivers I guess. That's what the Logitech drivers do, I don't know what the PID driver does.

@Spacefreak18
Copy link
Contributor

I changed the behaviour in the OpenFFBoard firmware back to treating 0xffff and 0 as infinite. The PID standard is not fully clear about if the maximum or 0 is treated as infinite. Check the definitions page of the PID document. That indicates to me that it is likely the max value. Never seen anything on windows send 0. Windows always uses the maximum but also no game would send 0 it seems so its probably best to treat both as infinite for compatibility reasons.

But there are currently other issues. I can't get FFB at all to work on my linux machine at the moment to test it.

Maybe someone here has an idea. dmesg always reports implement() called with too large value 4 (n: 1)! which hints at core-hid.c and sometimes when an effect should be loaded it reports upload request failed.

device reports 0 simultaneous effects
pid_block_load failed 60 times
upload request failed

But the device never receives an effect request at all for some reason so it could be a descriptor interpretation problem on linux. Linux seems very strict about what fields must be present in the descriptor in what order with which values while on windows the descriptor defines what capabilities the device has and the OS sends reports accordingly.

you have no idea how long i've been searching the internet to find someone who came across that implement error. i've been neck deep in Linux Force Feedback weeds all month, and I came across this repo fairly early, but I didn't take the time to read the issues.

I have a SimXperience Accuforce V2 wheel, which also uses the generic kernel pidff driver. And while tools like ffbtest will work just fine, it wasn't working through wine.

I too have noticed that implement error. but i sort of moved on from it because i think it was a bit of a red herring, or atleast not my biggest issue. i think it only applies to certain effects, i think Rumble, but don't quote me on that. Which would make sense if more common wheels that only have limited common effects, don't see that error.

the biggest issue was the -1 coming from wine dinput into SDL. i put a few lines to set replay.length to SHRT_MAX and i could get ForceTest.exe to play effects.

atleast better. i still think there are other issues i'm working through.

i started a wine thread but now i'm unsure whether or not wine should be sending SHRT_MAX or if SDL should understand and handle the -1.

@groybe
Copy link
Author

groybe commented Aug 29, 2022

I too have noticed that implement error. but i sort of moved on from it because i think it was a bit of a red herring, or atleast not my biggest issue. i think it only applies to certain effects, i think Rumble, but don't quote me on that. Which would make sense if more common wheels that only have limited common effects, don't see that error.

I guess it would affect any effect the uses infinite duration. In my case it was Constant Force but I've only tried Richard Burns Rally.

Also looking at the work around I was using here I had a problem with the wheel not listening to a negative direction but direction based on degrees was ok. I forget why this was. I think it was the wheel's handling of it too.

@groybe
Copy link
Author

groybe commented Aug 29, 2022

I just read your post over at Wine forum. Yeah now I remember wine 7 doesn't work for me. So you're not the only one. https://bugs.winehq.org/show_bug.cgi?id=52714

@Spacefreak18
Copy link
Contributor

i actually just looked again, and i do see that implement error regardless of the effect. but it's just a warning, and the effect still plays. i'll need to investigate further to see if that's causing the problems i'm seeing, which i may create another thread for.

i also looked at your "override length" addition to the ffbwrapper. It'll just set the length to 0xFFFF when it is enabled, so even if the effect had some other reasonable value, it'll just be ignored. i guess most applications will not use values that are non-zero and not max?

@groybe
Copy link
Author

groybe commented Aug 29, 2022

I think on other effects like sine and rumble the duration would matter yeah. So it really would only work with a game that constantly updates the effect. I guess that would be how most games would use constant force where the duration is really irrelevant as long as it has at least some.

Most of this is over my head though.

@berarma
Copy link
Owner

berarma commented Aug 29, 2022

I have a SimXperience Accuforce V2 wheel, which also uses the generic kernel pidff driver. And while tools like ffbtest will work just fine, it wasn't working through wine.

Does it work with Wine/Proton 6? There were some breaking changes in Wine/Proton 7.

It would be interesting to know more about other PID compatible wheels. More testing would probably help fix bugs unconvered until now. I see there might be discrepancies as to what the different Linux FF drivers understand as infinite. Wine/Proton/SDL might have get caught by these discrepancies.

@Spacefreak18
Copy link
Contributor

berama, i've read that too but I just can't replicate that. I can get wine 7 to work with the version in debian and with the latest from git. As long as i patch SDL with the -1 issue here.

Now, of course, whe I use proton i have to force it to use the system version of SDL by specifiying SDL_DYNAMIC_API=/usr/local/lib/libSDL2.

This is a very confusing landscape, with a lot of moving parts, wine potentially changing backends does not help the matter. I was constantly playing with a registry key in wine (DisableHidraw) thinking that had something to do with it.

@Spacefreak18
Copy link
Contributor

Here's a link to the patch i'm using on SDL right now if anyone finds it helpful.
https://gist.github.com/Spacefreak18/50e27015bdfeb1c9a4da7d3e1b03dff5

@Spacefreak18
Copy link
Contributor

I changed the behaviour in the OpenFFBoard firmware back to treating 0xffff and 0 as infinite. The PID standard is not fully clear about if the maximum or 0 is treated as infinite. Check the definitions page of the PID document. That indicates to me that it is likely the max value. Never seen anything on windows send 0. Windows always uses the maximum but also no game would send 0 it seems so its probably best to treat both as infinite for compatibility reasons.

But there are currently other issues. I can't get FFB at all to work on my linux machine at the moment to test it.

Maybe someone here has an idea. dmesg always reports implement() called with too large value 4 (n: 1)! which hints at core-hid.c and sometimes when an effect should be loaded it reports upload request failed.

device reports 0 simultaneous effects
pid_block_load failed 60 times
upload request failed

But the device never receives an effect request at all for some reason so it could be a descriptor interpretation problem on linux. Linux seems very strict about what fields must be present in the descriptor in what order with which values while on windows the descriptor defines what capabilities the device has and the OS sends reports accordingly.

also, i think that upload request failed, could be related to the fix of --update-fix in the ffbwrapper. Have you tried that?

@berarma
Copy link
Owner

berarma commented Sep 6, 2022

I changed the behaviour in the OpenFFBoard firmware back to treating 0xffff and 0 as infinite. The PID standard is not fully clear about if the maximum or 0 is treated as infinite. Check the definitions page of the PID document. That indicates to me that it is likely the max value. Never seen anything on windows send 0. Windows always uses the maximum but also no game would send 0 it seems so its probably best to treat both as infinite for compatibility reasons.
But there are currently other issues. I can't get FFB at all to work on my linux machine at the moment to test it.
Maybe someone here has an idea. dmesg always reports implement() called with too large value 4 (n: 1)! which hints at core-hid.c and sometimes when an effect should be loaded it reports upload request failed.

device reports 0 simultaneous effects
pid_block_load failed 60 times
upload request failed

But the device never receives an effect request at all for some reason so it could be a descriptor interpretation problem on linux. Linux seems very strict about what fields must be present in the descriptor in what order with which values while on windows the descriptor defines what capabilities the device has and the OS sends reports accordingly.

also, i think that upload request failed, could be related to the fix of --update-fix in the ffbwrapper. Have you tried that?

The "--update-fix" option was added to work around a bug in kernels prior to 5.8. The symptoms are very similar to what's described here. Please, see ValveSoftware/Proton#2366 (comment)

With kernels 5.8 and newer there shouldn't be a need for this work around unless another similar issue has arised. Stable kernels with updates after that should have the fix too as stated in the linked post.

@Spacefreak18
Copy link
Contributor

Spacefreak18 commented Sep 9, 2022

I'm going to try to keep this thread on topic and only talk about the infinite effect duration. In short, i thought update fix was doing something, but it was really just a difference in wine 5 vs wine 7.

Also, there is an obvious error in the first patch i made, but this has made me more certain that the bug here is within wine not SDL though that is where I've been writing this patch.

Previously when the SDL effect came in as -1 I was setting the length to the maximum value of a signed short, in the Linux Kernel source code, it is an unsigned short. I made an updated patch here.

That's what was causing the issue of the effects just stopping that i reported on the previous thread.

In my patch I went ahead and put some logic to set other values to their maxes, but just the adjusting the lengths should be sufficient to atlest get effects to play, they may be inaccurate, I don't know.

Which brings me to the larger issue...

It clearly has to be a wine bug, let's take a simple constant force effect as an example. replay length is an unsigned short, and constant force level is a signed short in the linux kernel. So for the length, obviously if -1 is passed to SDL, it would be an invalid value to pass to the linux kernel effect, so we can just force it to the SHRT_MAX. But we can't do the same for the constant force level setting, it being an unsigned short in the linux kernel, -1 is actually a valid value.

edited for clarity hopefully.

edit: i just read again that values above 0x7fff are unspecified, so now i really don't know what to do. and setting an unsigned short to -1, should set it to max.

edit: i'll study what's going on some more, but i should add that with that patch i made, not only do effects play, i did 3 full laps with the Accuforce v2 in Assetto Corsa on Linux!

@Spacefreak18
Copy link
Contributor

The Linux FF API is different to Windows. The Linux source code has this comment:

All duration values are expressed in ms. Values above 32767 ms (0x7fff) should not be used and have unspecified results.

So using 0xFFFF can give unexpected results, it could even work but it's not following the API specs.

I checked again and indeed in our firmware the maximum valid range is until 0x7fff but windows will send 0xffff as infinite. According to the PID document the "maximum of a range" is infinite so for a 16b value that might actually be 0xffff here and not the maximum of the defined valid range of a value which is 0x7fff then.

i think what my findings are showing is that there is atleast one other PID device in the wild that is expecting 0xffff as infinite rather than 0x7fff.

Where does the 0x7fff come from other than those comments in the linux source code?

@berarma
Copy link
Owner

berarma commented Sep 9, 2022

I think we're mixing PID docs and the Linux API. While infinite is defined as the max in the PID docs, that's not how it's defined in the Linux API. So 0x7FFF is not infinite.

I came to the conclusion that 0 was infinite for the Linux API from code in the Logitech driver. I don't think it's written anywhere except in code.

After taking a look at the PID module it seems as if it didn't translate the Linux API infinite value (0) to the PID infinite value (0xFFFF). Someone else should confirm this.

Double checking what I said is more than welcome.

@Spacefreak18
Copy link
Contributor

Shouldn't the Linux API be driver agnostic?

I feel like the PID Document is implying that 0xFFFF is infinite since it would be the max for an unsigned short.

Are you implying hid-pidff.c should transate the zero to 0xffff? It wouldn't make sense to ever have an effect with zero length I'm guessing.

@berarma
Copy link
Owner

berarma commented Sep 9, 2022

Are you implying hid-pidff.c should transate the zero to 0xffff? It wouldn't make sense to ever have an effect with zero length I'm guessing.

Yes. It doesn't make any sense, that's why it's a good value to represent infinite. If other drivers are using 0 as infinite, the pidff driver should do the same I guess.

@Spacefreak18
Copy link
Contributor

I went ahead and submitted this as a patch to the kernel, it looks like it may get accepted.

https://lkml.org/lkml/2022/10/2/99

@berarma
Copy link
Owner

berarma commented Oct 6, 2022

I went ahead and submitted this as a patch to the kernel, it looks like it may get accepted.

https://lkml.org/lkml/2022/10/2/99

Good. It's now clear there wasn't a consensus on how infinite was represented but Wine has favoured 0 as inifinite. I just checked Dirt Rally, a native port by Feral and it uses 0x7FFF for duration. They probably got confused too and decided to use the longest possible value. It doesn't really matter when you're updating effects periodically every fraction of a second.

Fixing this might allow using several high-end DD wheels. I'd love to have a list of the wheel models that would suddenly work. Fixing the iforce module would also fix some older wheels.

Thanks!

@Ultrawipf
Copy link

The value will depend on the range defined in the HID descriptor. In our firmware and most other devices it is defined as

0x09,0x50,         //    Usage Duration
0x09,0x54,         //    Usage Trigger Repeat Interval. Unused
0x09,0x51,         //    Usage Sample Period
0x09,0xA7,         //    Usage Start Delay
0x15,0x00,         //    Logical Minimum 0
0x26,0xFF,0x7F,    //    Logical Maximum 7FFFh (32767d)

so 0 to 0x7fff and windows games will send 0xffff as infinite. So for example if a device defines the range as only 8 bits the maximum should also only be 0xff for compatibility.

In general many things in the linux implementation are very strict disregarding the descriptor and won't be compatible with all devices. It fails when optional fields the device doesn't even support are missing or in a different order like the trigger interval/buttons. The whole point of the descriptor is to report to the computer how the expected reports should be structured and what it supports. Never seen a modern device use the triggers or custom force effects but if you leave it out of the descriptor because its not supported it will not work outside of windows.

@Spacefreak18
Copy link
Contributor

Leaving the Windows side aside for the moment, Wine will still send 0, but for your firmware, based on that descriptor, you'd have to set 0x7fff for infinite.

Will 0x7fff create an infinite length effect in your firmware?

If so, I think I can modify my patch to read the value at 0x26 in the descriptor and use it to set infinite on 0 length effects.

It'll be a 16 bit value so I have no idea how it will work on a device that wants to use an 8 bit value there.

As for Windows, does it send 0xffff to your device to indicate an infinite length effect? Thereby ignoring your descriptor? What's the behavior then?

@Ultrawipf
Copy link

Will 0x7fff create an infinite length effect in your firmware?

At the moment no. Only 0xffff and 0 but it could be modified to >= 0x7fff in case thats a valid value too.
Not sure if 0x7fff as infinite would be the standard or not. I never ran into issues with that yet and have always only seen 0xffff for 16b 0-0x7fff duration ranges.

If so, I think I can modify my patch to read the value at 0x26 in the descriptor and use it to set infinite on 0 length effects.

It'll be a 16 bit value so I have no idea how it will work on a device that wants to use an 8 bit value there.

As for Windows, does it send 0xffff to your device to indicate an infinite length effect? Thereby ignoring your descriptor? What's the behavior then?

Yes it does. I have tested the behaviour with fedit which is an old microsoft FFB effect testing tool and iracing wheelcheck.
Both send 0xffff when infinite.

Simucube also defines a 0 to 32767 range in their descriptor and also seems to receive 0xffff in the usb packet so i would assume at least according to Microsofts dinput infinite is not the highest value defined in the descriptor but the highest value of the datatype.

@groybe
Copy link
Author

groybe commented Oct 13, 2022

I'm going to try to keep this thread on topic and only talk about the infinite effect duration. In short, i thought update fix was doing something, but it was really just a difference in wine 5 vs wine 7.

Also, there is an obvious error in the first patch i made, but this has made me more certain that the bug here is within wine not SDL though that is where I've been writing this patch.

Previously when the SDL effect came in as -1 I was setting the length to the maximum value of a signed short, in the Linux Kernel source code, it is an unsigned short. I made an updated patch here.

That's what was causing the issue of the effects just stopping that i reported on the previous thread.

In my patch I went ahead and put some logic to set other values to their maxes, but just the adjusting the lengths should be sufficient to atlest get effects to play, they may be inaccurate, I don't know.

Which brings me to the larger issue...

It clearly has to be a wine bug, let's take a simple constant force effect as an example. replay length is an unsigned short, and constant force level is a signed short in the linux kernel. So for the length, obviously if -1 is passed to SDL, it would be an invalid value to pass to the linux kernel effect, so we can just force it to the SHRT_MAX. But we can't do the same for the constant force level setting, it being an unsigned short in the linux kernel, -1 is actually a valid value.

edited for clarity hopefully.

edit: i just read again that values above 0x7fff are unspecified, so now i really don't know what to do. and setting an unsigned short to -1, should set it to max.

edit: i'll study what's going on some more, but i should add that with that patch i made, not only do effects play, i did 3 full laps with the Accuforce v2 in Assetto Corsa on Linux!

Is Assetto Corsa working on wine 7 for you?
I still need to use wine 6 for Richard Burns Rally so now I'm thinking there is a separate issue specific to RBR.

@Spacefreak18
Copy link
Contributor

I'm going to try to keep this thread on topic and only talk about the infinite effect duration. In short, i thought update fix was doing something, but it was really just a difference in wine 5 vs wine 7.
Also, there is an obvious error in the first patch i made, but this has made me more certain that the bug here is within wine not SDL though that is where I've been writing this patch.
Previously when the SDL effect came in as -1 I was setting the length to the maximum value of a signed short, in the Linux Kernel source code, it is an unsigned short. I made an updated patch here.
That's what was causing the issue of the effects just stopping that i reported on the previous thread.
In my patch I went ahead and put some logic to set other values to their maxes, but just the adjusting the lengths should be sufficient to atlest get effects to play, they may be inaccurate, I don't know.
Which brings me to the larger issue...
It clearly has to be a wine bug, let's take a simple constant force effect as an example. replay length is an unsigned short, and constant force level is a signed short in the linux kernel. So for the length, obviously if -1 is passed to SDL, it would be an invalid value to pass to the linux kernel effect, so we can just force it to the SHRT_MAX. But we can't do the same for the constant force level setting, it being an unsigned short in the linux kernel, -1 is actually a valid value.
edited for clarity hopefully.
edit: i just read again that values above 0x7fff are unspecified, so now i really don't know what to do. and setting an unsigned short to -1, should set it to max.
edit: i'll study what's going on some more, but i should add that with that patch i made, not only do effects play, i did 3 full laps with the Accuforce v2 in Assetto Corsa on Linux!

Is Assetto Corsa working on wine 7 for you? I still need to use wine 6 for Richard Burns Rally so now I'm thinking there is a separate issue specific to RBR.

Wine 7 breaks ForceFeedback for me, even with the above mentioned patch. And I'm pretty sure it's inside Wine. I tried changine winesys backends, etc, with no results.

The guide I used to install Assetto Corsa, suggested installing to a Proton 5 prefix, and then upgrading to a Proton 6.3 prefix, and that is what I am currently using.

I tried upgrading all the way to Proton 7 and that broke Assetto Corsa completely too for me. But I didn't try much. I also had problems installing dotnet into 7.

In short, 7 breaks a lot of things for me, that I'm ignoring for the moment.

#27

@groybe
Copy link
Author

groybe commented Oct 15, 2022

Ah. I was reading some people over at the WIneHQ Bugzilla were having some success with 7 but it's gone quiet over there now.
Wine 6 for now then :)

@berarma
Copy link
Owner

berarma commented Dec 19, 2022

Today I've investigated this log because this game hasn't good FFB on Linux with Proton.

I've found Wine uses the internal value 0xffff for infinity (I don't know if this is what Windows uses too). And this value becomes SDL_HAPTIC_INFINITY when calling SDL.

https://github.com/ValveSoftware/wine/blob/492470267af486cb24ad0deaa028168eb94618a4/dlls/winebus.sys/bus_sdl.c#L714

SDL then calls the Linux API with duration 0 for infinity or 1-32767.

https://github.com/libsdl-org/SDL/blob/5c29b58e954dddd7beba22a7df3efbc8d410abc4/src/haptic/linux/SDL_syshaptic.c#L731

I guess this confirms the Linux FFB API uses 0 for infinity, while WIndows and SDL use different values.

In the log for this game the duration of effects is set to 0x7fff, thus they last for around 32s. The game downloads and starts playing the effects when it starts running, and doesn't update them until the driving starts, later than 32s. When the first effect update arrives the effect has already stopped playing and it's ignored.

My first thought was that Wine wasn't correctly setting the infinity value, but after checking the code in the above links it seems likely that that's not the case.

Do you know if an update for an effect that has already stopped because it reached its time duration should start playing the effect again?

@groybe
Copy link
Author

groybe commented Dec 20, 2022

There were some new changes in latest wine to fix FFB in FH5. Although a different issue. Possibly it already does reset the timer after the effect update? See the last commit here.
https://gitlab.winehq.org/wine/wine/-/merge_requests/1535/commits?commit_id=496f7c61348825d735e10878d04c190cc92b8729

@berarma
Copy link
Owner

berarma commented Dec 20, 2022

There were some new changes in latest wine to fix FFB in FH5. Although a different issue. Possibly it already does reset the timer after the effect update? See the last commit here. https://gitlab.winehq.org/wine/wine/-/merge_requests/1535/commits?commit_id=496f7c61348825d735e10878d04c190cc92b8729

Interesting. That commit describes the issue but that's not what I'm seeing in the FFB logs. The logs were created using Proton Bleeding Edge which I assume has this changes implemented. I'm surprised they didn't see the other issue. This is about the duration of the effect.

@Spacefreak18
Copy link
Contributor

I'd be interested to hear what the firmware guys have to say, because I think unless you call erase/stop explicitly, there's no other way the effect will be deleted from the device unless the firmware is handling it, even if that effect has since "expired". I'm only speculating that this could have caused some of the weird "sync" issues i experienced in some tools where one effect would actually play a completely different effect.

I think it's something we should strive to get right, but making sure we have a common infinite is more important. Because for the most part, a game is going to upload all the effects it's going to use at the beginning, with infinite duration, and just update them as necessary, and delete them when you're done.

@Ultrawipf
Copy link

I'd be interested to hear what the firmware guys have to say, because I think unless you call erase/stop explicitly, there's no other way the effect will be deleted from the device unless the firmware is handling it, even if that effect has since "expired". I'm only speculating that this could have caused some of the weird "sync" issues i experienced in some tools where one effect would actually play a completely different effect.

Usually effects persist until they are individually deleted or a reset is sent. An effect timer running out only disables it like if the stop command would be sent for this effect.
There is also a reset command which also removes all effects in our firmware and disables the ffb. The PID specification defines the reset action to ENABLE actuators and clear all effects so clearing effects is specified.

One note regarding FH5: It does not enable and disable effects. Instead it enables all effects and uses the separate effect gain to disable unused effects by setting it to 0. Not all devices may implement it and this is the first game i have seen that even touches the gain at all. This means if a device does not handle the gain at startup a bunch of overlapping sine vibrations would be active.

@berarma
Copy link
Owner

berarma commented Dec 21, 2022

I'd be interested to hear what the firmware guys have to say, because I think unless you call erase/stop explicitly, there's no other way the effect will be deleted from the device unless the firmware is handling it, even if that effect has since "expired". I'm only speculating that this could have caused some of the weird "sync" issues i experienced in some tools where one effect would actually play a completely different effect.

Usually effects persist until they are individually deleted or a reset is sent. An effect timer running out only disables it like if the stop command would be sent for this effect.

That's what I meant. They're fixing now some bugs in WGI in Proton.

There is also a reset command which also removes all effects in our firmware and disables the ffb. The PID specification defines the reset action to ENABLE actuators and clear all effects so clearing effects is specified.

One note regarding FH5: It does not enable and disable effects. Instead it enables all effects and uses the separate effect gain to disable unused effects by setting it to 0. Not all devices may implement it and this is the first game i have seen that even touches the gain at all. This means if a device does not handle the gain at startup a bunch of overlapping sine vibrations would be active.

There's no separate gain on Linux. Proton translates it to changing effect parameters.

@berarma berarma added the question Further information is requested label Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants