# encoding: utf-8 import ctypes from evdev import ecodes _u8 = ctypes.c_uint8 _u16 = ctypes.c_uint16 _u32 = ctypes.c_uint32 _s16 = ctypes.c_int16 class Replay(ctypes.Structure): ''' Defines scheduling of the force-feedback effect @length: duration of the effect @delay: delay before effect should start playing ''' _fields_ = [ ('length', _u16), ('delay', _u16), ] class Trigger(ctypes.Structure): ''' Defines what triggers the force-feedback effect @button: number of the button triggering the effect @interval: controls how soon the effect can be re-triggered ''' _fields_ = [ ('button', _u16), ('interval', _u16), ] class Envelope(ctypes.Structure): ''' Generic force-feedback effect envelope @attack_length: duration of the attack (ms) @attack_level: level at the beginning of the attack @fade_length: duration of fade (ms) @fade_level: level at the end of fade The @attack_level and @fade_level are absolute values; when applying envelope force-feedback core will convert to positive/negative value based on polarity of the default level of the effect. Valid range for the attack and fade levels is 0x0000 - 0x7fff ''' _fields_ = [ ('attach_length', _u16), ('attack_level', _u16), ('fade_length', _u16), ('fade_level', _u16), ] class Constant(ctypes.Structure): ''' Defines parameters of a constant force-feedback effect @level: strength of the effect; may be negative @envelope: envelope data ''' _fields_ = [ ('level', _s16), ('ff_envelope', Envelope), ] class Ramp(ctypes.Structure): ''' Defines parameters of a ramp force-feedback effect @start_level: beginning strength of the effect; may be negative @end_level: final strength of the effect; may be negative @envelope: envelope data ''' _fields_ = [ ('start_level', _s16), ('end_level', _s16), ('ff_envelope', Envelope), ] class Condition(ctypes.Structure): ''' Defines a spring or friction force-feedback effect @right_saturation: maximum level when joystick moved all way to the right @left_saturation: same for the left side @right_coeff: controls how fast the force grows when the joystick moves to the right @left_coeff: same for the left side @deadband: size of the dead zone, where no force is produced @center: position of the dead zone ''' _fields_ = [ ('right_saturation', _u16), ('left_saturation', _u16), ('right_coeff', _s16), ('left_foeff', _s16), ('deadband', _u16), ('center', _s16), ] class Periodic(ctypes.Structure): ''' Defines parameters of a periodic force-feedback effect @waveform: kind of the effect (wave) @period: period of the wave (ms) @magnitude: peak value @offset: mean value of the wave (roughly) @phase: 'horizontal' shift @envelope: envelope data @custom_len: number of samples (FF_CUSTOM only) @custom_data: buffer of samples (FF_CUSTOM only) ''' _fields_ = [ ('waveform', _u16), ('period', _u16), ('magnitude', _s16), ('offset', _s16), ('phase', _u16), ('envelope', Envelope), ('custom_len', _u32), ('custom_data', ctypes.POINTER(_s16)), ] class Rumble(ctypes.Structure): ''' Defines parameters of a periodic force-feedback effect @strong_magnitude: magnitude of the heavy motor @weak_magnitude: magnitude of the light one Some rumble pads have two motors of different weight. Strong_magnitude represents the magnitude of the vibration generated by the heavy one. ''' _fields_ = [ ('strong_magnitude', _u16), ('weak_magnitude', _u16), ] class EffectType(ctypes.Union): _fields_ = [ ('ff_constant_effect', Constant), ('ff_ramp_effect', Ramp), ('ff_periodic_effect', Periodic), ('ff_condition_effect', Condition * 2), # one for each axis ('ff_rumble_effect', Rumble), ] class Effect(ctypes.Structure): _fields_ = [ ('type', _u16), ('id', _s16), ('direction', _u16), ('ff_trigger', Trigger), ('ff_replay', Replay), ('u', EffectType) ] # ff_types = { # ecodes.FF_CONSTANT, # ecodes.FF_PERIODIC, # ecodes.FF_RAMP, # ecodes.FF_SPRING, # ecodes.FF_FRICTION, # ecodes.FF_DAMPER, # ecodes.FF_RUMBLE, # ecodes.FF_INERTIA, # ecodes.FF_CUSTOM, # }