gvalkov / python-evdev

Python bindings for the Linux input subsystem
https://python-evdev.rtfd.org/
BSD 3-Clause "New" or "Revised" License
331 stars 109 forks source link

Effect "FF_CONSTANT" with G920 #122

Open andreaslindner opened 4 years ago

andreaslindner commented 4 years ago

It seems like this simple effect should work but I cannot see how this is supposed to be used. Possibly I am doing something wrong and help is much appreciated. (However, I am able to successfully read axis update events as well as rumble and autocenter the steering wheel. This means that the basic setup works.)

This is the code I tried first, but it does nothing except that the wheel seemingly sends an acknowledgment for triggering the event:

#!/usr/bin/env python3

import time
import evdev
from evdev import ecodes, InputDevice, ff

# Find first EV_FF capable event device (that we have permissions to use).
for name in evdev.list_devices():
    dev = InputDevice(name)
    if ecodes.EV_FF in dev.capabilities():
        break

envelope = ff.Envelope(500, 1000, 500, 1000)                                                                            
constant = ff.Constant(10000, envelope)

duration_ms = 1000
effect = ff.Effect(
  ecodes.FF_CONSTANT, -1, 1,
  ff.Trigger(0, 0),
  ff.Replay(duration_ms, 0),
  ff.EffectType(ff_constant_effect=constant)
)

repeat_count = 1
effect_id = dev.upload_effect(effect)
try:
        dev.write(ecodes.EV_FF, effect_id, repeat_count)
        input("press enter when done")
finally:
        dev.erase_effect(effect_id)

Then I started digging and ended up in the kernel driver for HID++, see here. When looking at this it seems that the value of direction for the ff.Effect has to be quite high so that force does not become zero because of the right shifts in force = (effect->u.constant.level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;. Then I started to make this and related values such that sensible values for force should be the result. This had also no effect as well as trying to make it ridiculously high.

Am I missing something terribly obvious? :)

andreaslindner commented 4 years ago

Ok. I found the problem. I didn't know that direction means something like angle of force. This code works and I can use it to change the force from a single variable:

#!/usr/bin/env python3

import time
import evdev
from evdev import ecodes, InputDevice, ff

# Find first EV_FF capable event device (that we have permissions to use).
for name in evdev.list_devices():
    dev = InputDevice(name)
    if ecodes.EV_FF in dev.capabilities():
        break

                                                                                                                       envelope = ff.Envelope(0, 0, 0, 0)                                                                                     
force = -0.3                                                                                                           constant = ff.Constant(int(force * (65535 / 2)), envelope)
                                                                                                                       effect = ff.Effect(
  ecodes.FF_CONSTANT, -1, 16384,
  ff.Trigger(0, 0),
  ff.Replay(0, 0),
  ff.EffectType(ff_constant_effect=constant)
)

repeat_count = 1
effect_id = dev.upload_effect(effect)
try:
        dev.write(ecodes.EV_FF, effect_id, repeat_count)
        input("press enter when done")
finally:
        dev.erase_effect(effect_id)

Notice that direction has now value 16384, which corresponds to a 90 degree angle.

Maybe somebody wants to add an example in the documentation or a comment on how the parameters are interpreted or something?