berarma / ffbtools

Set of tools for FFB testing and debugging on GNU/Linux
GNU General Public License v3.0
56 stars 10 forks source link

draft: fix for extreme delay (even with throttling) on logitech g920 #31

Closed ryannathans closed 1 month ago

ryannathans commented 1 year ago

The Logitech G920 uses a HID++ driver that seems to poorly handle play commands. The HID++ spec doesn't even seem to have a play command so who knows what this is getting translated into without diving into the kernel driver code. Spec: https://opensource.logitech.com/wiki/force_feedback/Logitech_Force_Feedback_Protocol_V1.6.pdf

It seems that the play command is only ever required to enable an effect slot, and handling a play on the G920 is extremely slow. Some games like F1 2022 and Dirt Rally 2.0 seem to spam a huge quantity of play commands, causing extreme delay in ffb, even with throttling.

With this patch, and setting --throttling-time to 5 (200hz), I no longer see Force feedback command queue contains x commands, causing substantial delays! in dmesg apart from when play commands are sent when ffb is initially configured when starting a game.

I intend to test this patch on a ffb wheel using the other more mainstream driver like the G29 to see how it handles it and what the behavior of play is. This enhancement on throttling may require moving into another command line parameter if it interferes with operation on wheels that don't use HID++.

I would appreciate some review from someone with more than 12 hours experience in force feedback magic :)

berarma commented 1 year ago

Merging this PR would introduce an issue because effects can stop without a stop command. When the effect is played the number of times specified in the count argument of the play command for the time specified in the length field of the effect, or when the play command has a count of zero, in both cases the effect will stop.

I propose changing the way it works. Play commands on effects with an infinite length (length:0) can be ignored, unless the count is zero.

I would add a new parameter for this (like --ignore-redundant-play) and then check the length of the previous update command and the count argument of the play command, when length is zero and count is not zero the play command can be ignored.

I'm not 100% sure but I think this would be correct only for effects of type constant, spring, damper, inertia and rumble. So we should check for these effect types too.

ryannathans commented 1 year ago

I would add a new parameter for this (like --ignore-redundant-play) and then check the length of the previous update command and the count argument of the play command, when length is zero and count is not zero the play command can be ignored.

This makes a lot more sense for a properly implemented approach.

I suspect something is very wrong with the processing of play commands for the G920 as even with this draft PR I get a few hundred commands queued in F1 22 every time I pause and resume the game - when 2 play commands are sent. The same game works just fine on the G29 with no throttling at all.

If I am understanding correctly, the logs the tool generates are the commands from the game being sent to the kernel driver?

I'll rewrite this PR taking your feedback into account once I understand what is going on with the huge delays on the G920 after each play command.

berarma commented 1 year ago

I would add a new parameter for this (like --ignore-redundant-play) and then check the length of the previous update command and the count argument of the play command, when length is zero and count is not zero the play command can be ignored.

This makes a lot more sense for a properly implemented approach.

I suspect something is very wrong with the processing of play commands for the G920 as even with this draft PR I get a few hundred commands queued in F1 22 every time I pause and resume the game - when 2 play commands are sent. The same game works just fine on the G29 with no throttling at all.

If I am understanding correctly, the logs the tool generates are the commands from the game being sent to the kernel driver?

It catches the commands sent to the libc ioctl and write calls, but it should be the same commands that the driver receives.

I'll rewrite this PR taking your feedback into account once I understand what is going on with the huge delays on the G920 after each play command.

You can enable debug information for the kernel without recompiling. Read https://www.kernel.org/doc/html/v5.0/admin-guide/dynamic-debug-howto.html

You can also use Wireshark to capture USB packets and analyze timings.

There might be other ways to debug the USB stack. I haven't looked much into it. Try searching for this topic.

ryannathans commented 1 year ago

that's smart with the wireshark idea, I'll compare logs and wireshark dumps from the same game on the G920 and the G29 and see if there's an obvious reason for this

berarma commented 1 month ago

Commit 3035e0e52de3dfc5bffaee1abf135dfa99fea5ff implements a different solution for the same issue this PR tried to solve. Please test and report back.