-
Notifications
You must be signed in to change notification settings - Fork 20
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
FFB not work as expect when direction changed #43
Comments
Hi, could you clarify what you mean by 'fails'? Is there an error in Other than that, I think one issue might be with
The kernel docs in https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/input.h#L302 say
Assuming that Also a sidenote, in https://www.kernel.org/doc/html/latest/input/ff.html#dynamic-update-of-an-effect changing the direction of an effect dynamically is not recommended. I'm pretty sure my driver should handle the situation correctly, but might not work as expected on other wheels and from what I can remember doesn't work on Windows. |
when I set effect_.replay.length = 0xffff, ffb works as expected but will lose after almost 60s. I'll change it to 0, thanks for the suggestion. |
Right, yeah, my driver doesn't update the effect if only the direction changes, similar to how the Windows driver works. However, if you change the level of the FFB as well, the direction will be updated at the same time. Although don't rely on this, as stated earlier changing the direction of an effect dynamically isn't a well defined operation. |
That's not how it works on Linux. I don't see the point in making a Linux driver behave like the Windows one. It should work as defined by the Linux API or we'll see inconsistent behavior between different hardware. If you're worried about the driver working well on Wine/Proton is equally important to follow the Linux API because that's what Wine/Proton expects and will translate Windows calls accordingly. The Linux API doc doesn't say you shouldn't change direction dynamically. It says you should expect that some drivers stop and restart the effect when a dynamic change of direction is requested. So it's completely fine to change direction dynamically. The hardware has to support this or restart the effect with the new direction. |
Out of curiosity, is there more documentation about Linux FFB conventions than https://www.kernel.org/doc/html/latest/input/ff.html? I remember you having to correct me on
Lazy reading by me, sorry. The context of the restart is not well defined, not the act of changing direction then? Fair enough, should be a reasonably quick fix. |
Besides the API docs there's the headers file that defines the structs that has some comments. Nothing else that I know. The driver has to be able to change direction, either dynamically as requested in case the device supports it or by restarting the effect as a fallback. The docs say that some drivers might do a effect restart when requesting a dynamic direction change and the developer should be OK with that. The developer could also check that the devices they want to support do the right thing for their case. |
I pushed a test commit to https://github.com/Kimplul/hid-tmff2/tree/direction Don't have access to my wheel at the moment, please feel free to test the branch out. @Raboebie could you also check if it works? |
I try to install https://github.com/Kimplul/hid-tmff2/tree/direction but it still not working as expected.
Is it that the steering wheel firmware does not support this modification? |
No, the firmware doesn't actually have any concept of 'direction', my driver is just responsible for translating it down into something the wheel should understand. Apparently my driver is not working the way I expected it to, weird. Did you check that the newer driver is being loaded? Linux pretty often caches modules and you might still be running the old module. You could try adding something like And not to be condescending, but also check that you have the correct branch checked out in git. |
I'm sure I've check out the branch to direction. But I'm not sure if the new driver is used in the kernel (I don't know where I can see the output of printk? I didn't see it). |
That's pretty weird, might be a timing issue but I'll have to look into it. |
I hadn't looked at your code before but now that I did I've seen some things that I think should be commented. The direction parameter is a uint16 and for wheels should be 0x4000 (left) or 0xC000 (right). Other directions towards the vertical axis should fade out the effect since there's no vertical FFB. Changing the sign of direction has the effect of mirroring the effect to the other side. Even if it's unsigned it would work. You're sending effect updates every 8ms even if the effect changes only every 8s· I've tried the code on my G29 and it works only if I change the direction to 0x4000 or 0xC000. |
Could you share more about direction? I only see that
in this driver. |
The direction parameter is an angle expressed as an unsigned 16 bit integer with direction 0 pointing up and direction 0x8000 (180°) pointing down, running counter-clockwise. This is the direction of the force that will be applied and it's exactly how it works on joysticks that have FFB on both axes, X and Y. Since wheels have only one axis of movement, only the horizontal component of the force is used. With wheels, it doesn't make much sense using values other than 0x4000 or 0xC000 for the direction. They will work but only have the effect of reducing the total force applied. That line of code takes the horizontal component of the force requested in the parameters and applies it to the wheel. If the direction is up the horizontal component will be 0, if the direction is top/left (45°) the horizontal component will be half the total force, and if the direction is left (90°) the horizontal component will be 100% of the force. |
Thanks for your reply. |
I found something suspicious: |
Good point, I'll add a slight twist to that: The Looking at the code now though, it looks like I'm missing a negation and instead the effect is being updated on every user upload. Oops. At work right now so I can't test, but adding a Line 391 in f2950d2
It might also be worth making this relationship more obvious, for example changing |
It works like a charm! |
Are you sure all the comparisons of the current values with the old values are necessary? I remember avoiding them in new-lg4ff, I don't know if that would be possible here but it would sure make things simpler. For example, I see there's a comparison for the duration. Updating an effect with the same duration is still an update and it should make the effect last longer since the length counter is reset again to its initial value. With the level, I've seen the parameters are compared but not the final actual values. So the level that needs to apply might be different even though the level parameter is the same on the last and the current updates. Forgive if I make any mistake, I might have forgotten some details. |
No, not really, as previously mentioned I've mostly just been copying the Windows driver, which for example seems to not update the duration when the effect is modified (at least when done through
Seems reasonable, and if you're doing it I probably should too. Not to be rude, but where are you getting this information from? As I already mentioned, I know my driver is working like the Windows counterpart when it should be more like a Linux driver, but I honestly have no idea what behaviour is expected on Linux. I couldn't find a mention of this vs. the current behavour in the FFB docs nor the source code.
The final actual values (for level) are only affected by the direction and the level parameter, as far as I'm aware, and the driver checks if either of these parameters have changed since the last iteration. Or am I misunderstanding something? Anycase, if you have more insights, please feel free to update me on what else this driver might be doing differently from yours. Getting this driver to (finally?) behave consistently with other ones would be nice. Thanks for your help. |
The Linux docs don't explicitly talk about the duration parameter but defines dynamically updating an effect as loading a new one without needing to stop the current one. In addition, I based new-lg4ff on the existing hid-lg4ff driver and used it as reference. I think I managed to have the same behavior. I'm not 100% sure about everything so discussion is welcome. I should write some tests for ffbtools so we can see how the different drivers behave in these special situations. |
Will https://github.com/Kimplul/hid-tmff2/tree/direction be merged? |
@gou4shi1 Yes, thanks for reminding me, already forgot. |
I remember reading the ff-memless driver code since hid-lg4ff was based on it. It's a simple implementation of the Linux FFB API without hardware details. This base driver is intended for devices that only support one effect of each type played simultaneously. It keeps track of all the effects and mixes them so that the drivers based on it don't have to duplicate the code. I think it's a good reference for details that the Linux docs don't explicitly mention. In the function at https://github.com/torvalds/linux/blob/e0dccc3b76fb35bb257b4118367a883073d7390e/drivers/input/ff-memless.c#L465 we can see that a dynamical update does use the new duration and even the delay. So if an effect is updated with a delay of 1s and a duration of 2s the effect would pause for 1s then play for 2s independently of the older values. |
This is not strictly related to this ticket, but I'm my defence I apparently hadn't forgotten to apply the Compare Line 572 in f2950d2
and Line 572 in 9b1ae87
Not entirely sure what went wrong, but no harm done. |
+ According to discussion in #43 this is more along the lines of what other wheels do.
When I nagitive the direction of ffb effect, there is a high probability that force feedback not work. Unless I remove the effect and upload a new effect. Is it my misuse?
system: Ubuntu 16.04/20.04
my test code with compile command
gcc -std=c++14 t300rs.cc
:The text was updated successfully, but these errors were encountered: