162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Force feedback support for memoryless devices 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> 662306a36Sopenharmony_ci * Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* #define DEBUG */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/input.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/mutex.h> 1762306a36Sopenharmony_ci#include <linux/spinlock.h> 1862306a36Sopenharmony_ci#include <linux/jiffies.h> 1962306a36Sopenharmony_ci#include <linux/fixp-arith.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2262306a36Sopenharmony_ciMODULE_AUTHOR("Anssi Hannula <anssi.hannula@gmail.com>"); 2362306a36Sopenharmony_ciMODULE_DESCRIPTION("Force feedback support for memoryless devices"); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Number of effects handled with memoryless devices */ 2662306a36Sopenharmony_ci#define FF_MEMLESS_EFFECTS 16 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* Envelope update interval in ms */ 2962306a36Sopenharmony_ci#define FF_ENVELOPE_INTERVAL 50 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define FF_EFFECT_STARTED 0 3262306a36Sopenharmony_ci#define FF_EFFECT_PLAYING 1 3362306a36Sopenharmony_ci#define FF_EFFECT_ABORTING 2 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistruct ml_effect_state { 3662306a36Sopenharmony_ci struct ff_effect *effect; 3762306a36Sopenharmony_ci unsigned long flags; /* effect state (STARTED, PLAYING, etc) */ 3862306a36Sopenharmony_ci int count; /* loop count of the effect */ 3962306a36Sopenharmony_ci unsigned long play_at; /* start time */ 4062306a36Sopenharmony_ci unsigned long stop_at; /* stop time */ 4162306a36Sopenharmony_ci unsigned long adj_at; /* last time the effect was sent */ 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistruct ml_device { 4562306a36Sopenharmony_ci void *private; 4662306a36Sopenharmony_ci struct ml_effect_state states[FF_MEMLESS_EFFECTS]; 4762306a36Sopenharmony_ci int gain; 4862306a36Sopenharmony_ci struct timer_list timer; 4962306a36Sopenharmony_ci struct input_dev *dev; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci int (*play_effect)(struct input_dev *dev, void *data, 5262306a36Sopenharmony_ci struct ff_effect *effect); 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic const struct ff_envelope *get_envelope(const struct ff_effect *effect) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci static const struct ff_envelope empty_envelope; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci switch (effect->type) { 6062306a36Sopenharmony_ci case FF_PERIODIC: 6162306a36Sopenharmony_ci return &effect->u.periodic.envelope; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci case FF_CONSTANT: 6462306a36Sopenharmony_ci return &effect->u.constant.envelope; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci default: 6762306a36Sopenharmony_ci return &empty_envelope; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * Check for the next time envelope requires an update on memoryless devices 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic unsigned long calculate_next_time(struct ml_effect_state *state) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci const struct ff_envelope *envelope = get_envelope(state->effect); 7762306a36Sopenharmony_ci unsigned long attack_stop, fade_start, next_fade; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (envelope->attack_length) { 8062306a36Sopenharmony_ci attack_stop = state->play_at + 8162306a36Sopenharmony_ci msecs_to_jiffies(envelope->attack_length); 8262306a36Sopenharmony_ci if (time_before(state->adj_at, attack_stop)) 8362306a36Sopenharmony_ci return state->adj_at + 8462306a36Sopenharmony_ci msecs_to_jiffies(FF_ENVELOPE_INTERVAL); 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (state->effect->replay.length) { 8862306a36Sopenharmony_ci if (envelope->fade_length) { 8962306a36Sopenharmony_ci /* check when fading should start */ 9062306a36Sopenharmony_ci fade_start = state->stop_at - 9162306a36Sopenharmony_ci msecs_to_jiffies(envelope->fade_length); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (time_before(state->adj_at, fade_start)) 9462306a36Sopenharmony_ci return fade_start; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* already fading, advance to next checkpoint */ 9762306a36Sopenharmony_ci next_fade = state->adj_at + 9862306a36Sopenharmony_ci msecs_to_jiffies(FF_ENVELOPE_INTERVAL); 9962306a36Sopenharmony_ci if (time_before(next_fade, state->stop_at)) 10062306a36Sopenharmony_ci return next_fade; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return state->stop_at; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return state->play_at; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic void ml_schedule_timer(struct ml_device *ml) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct ml_effect_state *state; 11262306a36Sopenharmony_ci unsigned long now = jiffies; 11362306a36Sopenharmony_ci unsigned long earliest = 0; 11462306a36Sopenharmony_ci unsigned long next_at; 11562306a36Sopenharmony_ci int events = 0; 11662306a36Sopenharmony_ci int i; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci pr_debug("calculating next timer\n"); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci state = &ml->states[i]; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (!test_bit(FF_EFFECT_STARTED, &state->flags)) 12562306a36Sopenharmony_ci continue; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (test_bit(FF_EFFECT_PLAYING, &state->flags)) 12862306a36Sopenharmony_ci next_at = calculate_next_time(state); 12962306a36Sopenharmony_ci else 13062306a36Sopenharmony_ci next_at = state->play_at; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (time_before_eq(now, next_at) && 13362306a36Sopenharmony_ci (++events == 1 || time_before(next_at, earliest))) 13462306a36Sopenharmony_ci earliest = next_at; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (!events) { 13862306a36Sopenharmony_ci pr_debug("no actions\n"); 13962306a36Sopenharmony_ci del_timer(&ml->timer); 14062306a36Sopenharmony_ci } else { 14162306a36Sopenharmony_ci pr_debug("timer set\n"); 14262306a36Sopenharmony_ci mod_timer(&ml->timer, earliest); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Apply an envelope to a value 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic int apply_envelope(struct ml_effect_state *state, int value, 15062306a36Sopenharmony_ci struct ff_envelope *envelope) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci struct ff_effect *effect = state->effect; 15362306a36Sopenharmony_ci unsigned long now = jiffies; 15462306a36Sopenharmony_ci int time_from_level; 15562306a36Sopenharmony_ci int time_of_envelope; 15662306a36Sopenharmony_ci int envelope_level; 15762306a36Sopenharmony_ci int difference; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (envelope->attack_length && 16062306a36Sopenharmony_ci time_before(now, 16162306a36Sopenharmony_ci state->play_at + msecs_to_jiffies(envelope->attack_length))) { 16262306a36Sopenharmony_ci pr_debug("value = 0x%x, attack_level = 0x%x\n", 16362306a36Sopenharmony_ci value, envelope->attack_level); 16462306a36Sopenharmony_ci time_from_level = jiffies_to_msecs(now - state->play_at); 16562306a36Sopenharmony_ci time_of_envelope = envelope->attack_length; 16662306a36Sopenharmony_ci envelope_level = min_t(u16, envelope->attack_level, 0x7fff); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci } else if (envelope->fade_length && effect->replay.length && 16962306a36Sopenharmony_ci time_after(now, 17062306a36Sopenharmony_ci state->stop_at - msecs_to_jiffies(envelope->fade_length)) && 17162306a36Sopenharmony_ci time_before(now, state->stop_at)) { 17262306a36Sopenharmony_ci time_from_level = jiffies_to_msecs(state->stop_at - now); 17362306a36Sopenharmony_ci time_of_envelope = envelope->fade_length; 17462306a36Sopenharmony_ci envelope_level = min_t(u16, envelope->fade_level, 0x7fff); 17562306a36Sopenharmony_ci } else 17662306a36Sopenharmony_ci return value; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci difference = abs(value) - envelope_level; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci pr_debug("difference = %d\n", difference); 18162306a36Sopenharmony_ci pr_debug("time_from_level = 0x%x\n", time_from_level); 18262306a36Sopenharmony_ci pr_debug("time_of_envelope = 0x%x\n", time_of_envelope); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci difference = difference * time_from_level / time_of_envelope; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci pr_debug("difference = %d\n", difference); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return value < 0 ? 18962306a36Sopenharmony_ci -(difference + envelope_level) : (difference + envelope_level); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * Return the type the effect has to be converted into (memless devices) 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_cistatic int get_compatible_type(struct ff_device *ff, int effect_type) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (test_bit(effect_type, ff->ffbit)) 19962306a36Sopenharmony_ci return effect_type; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) 20262306a36Sopenharmony_ci return FF_RUMBLE; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci pr_err("invalid type in get_compatible_type()\n"); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return 0; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* 21062306a36Sopenharmony_ci * Only left/right direction should be used (under/over 0x8000) for 21162306a36Sopenharmony_ci * forward/reverse motor direction (to keep calculation fast & simple). 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_cistatic u16 ml_calculate_direction(u16 direction, u16 force, 21462306a36Sopenharmony_ci u16 new_direction, u16 new_force) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci if (!force) 21762306a36Sopenharmony_ci return new_direction; 21862306a36Sopenharmony_ci if (!new_force) 21962306a36Sopenharmony_ci return direction; 22062306a36Sopenharmony_ci return (((u32)(direction >> 1) * force + 22162306a36Sopenharmony_ci (new_direction >> 1) * new_force) / 22262306a36Sopenharmony_ci (force + new_force)) << 1; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#define FRAC_N 8 22662306a36Sopenharmony_cistatic inline s16 fixp_new16(s16 a) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci return ((s32)a) >> (16 - FRAC_N); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic inline s16 fixp_mult(s16 a, s16 b) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci a = ((s32)a * 0x100) / 0x7fff; 23462306a36Sopenharmony_ci return ((s32)(a * b)) >> FRAC_N; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* 23862306a36Sopenharmony_ci * Combine two effects and apply gain. 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_cistatic void ml_combine_effects(struct ff_effect *effect, 24162306a36Sopenharmony_ci struct ml_effect_state *state, 24262306a36Sopenharmony_ci int gain) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct ff_effect *new = state->effect; 24562306a36Sopenharmony_ci unsigned int strong, weak, i; 24662306a36Sopenharmony_ci int x, y; 24762306a36Sopenharmony_ci s16 level; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci switch (new->type) { 25062306a36Sopenharmony_ci case FF_CONSTANT: 25162306a36Sopenharmony_ci i = new->direction * 360 / 0xffff; 25262306a36Sopenharmony_ci level = fixp_new16(apply_envelope(state, 25362306a36Sopenharmony_ci new->u.constant.level, 25462306a36Sopenharmony_ci &new->u.constant.envelope)); 25562306a36Sopenharmony_ci x = fixp_mult(fixp_sin16(i), level) * gain / 0xffff; 25662306a36Sopenharmony_ci y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff; 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * here we abuse ff_ramp to hold x and y of constant force 25962306a36Sopenharmony_ci * If in future any driver wants something else than x and y 26062306a36Sopenharmony_ci * in s8, this should be changed to something more generic 26162306a36Sopenharmony_ci */ 26262306a36Sopenharmony_ci effect->u.ramp.start_level = 26362306a36Sopenharmony_ci clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f); 26462306a36Sopenharmony_ci effect->u.ramp.end_level = 26562306a36Sopenharmony_ci clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f); 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci case FF_RUMBLE: 26962306a36Sopenharmony_ci strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; 27062306a36Sopenharmony_ci weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (effect->u.rumble.strong_magnitude + strong) 27362306a36Sopenharmony_ci effect->direction = ml_calculate_direction( 27462306a36Sopenharmony_ci effect->direction, 27562306a36Sopenharmony_ci effect->u.rumble.strong_magnitude, 27662306a36Sopenharmony_ci new->direction, strong); 27762306a36Sopenharmony_ci else if (effect->u.rumble.weak_magnitude + weak) 27862306a36Sopenharmony_ci effect->direction = ml_calculate_direction( 27962306a36Sopenharmony_ci effect->direction, 28062306a36Sopenharmony_ci effect->u.rumble.weak_magnitude, 28162306a36Sopenharmony_ci new->direction, weak); 28262306a36Sopenharmony_ci else 28362306a36Sopenharmony_ci effect->direction = 0; 28462306a36Sopenharmony_ci effect->u.rumble.strong_magnitude = 28562306a36Sopenharmony_ci min(strong + effect->u.rumble.strong_magnitude, 28662306a36Sopenharmony_ci 0xffffU); 28762306a36Sopenharmony_ci effect->u.rumble.weak_magnitude = 28862306a36Sopenharmony_ci min(weak + effect->u.rumble.weak_magnitude, 0xffffU); 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci case FF_PERIODIC: 29262306a36Sopenharmony_ci i = apply_envelope(state, abs(new->u.periodic.magnitude), 29362306a36Sopenharmony_ci &new->u.periodic.envelope); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* here we also scale it 0x7fff => 0xffff */ 29662306a36Sopenharmony_ci i = i * gain / 0x7fff; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (effect->u.rumble.strong_magnitude + i) 29962306a36Sopenharmony_ci effect->direction = ml_calculate_direction( 30062306a36Sopenharmony_ci effect->direction, 30162306a36Sopenharmony_ci effect->u.rumble.strong_magnitude, 30262306a36Sopenharmony_ci new->direction, i); 30362306a36Sopenharmony_ci else 30462306a36Sopenharmony_ci effect->direction = 0; 30562306a36Sopenharmony_ci effect->u.rumble.strong_magnitude = 30662306a36Sopenharmony_ci min(i + effect->u.rumble.strong_magnitude, 0xffffU); 30762306a36Sopenharmony_ci effect->u.rumble.weak_magnitude = 30862306a36Sopenharmony_ci min(i + effect->u.rumble.weak_magnitude, 0xffffU); 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci default: 31262306a36Sopenharmony_ci pr_err("invalid type in ml_combine_effects()\n"); 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/* 32062306a36Sopenharmony_ci * Because memoryless devices have only one effect per effect type active 32162306a36Sopenharmony_ci * at one time we have to combine multiple effects into one 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_cistatic int ml_get_combo_effect(struct ml_device *ml, 32462306a36Sopenharmony_ci unsigned long *effect_handled, 32562306a36Sopenharmony_ci struct ff_effect *combo_effect) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci struct ff_effect *effect; 32862306a36Sopenharmony_ci struct ml_effect_state *state; 32962306a36Sopenharmony_ci int effect_type; 33062306a36Sopenharmony_ci int i; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci memset(combo_effect, 0, sizeof(struct ff_effect)); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { 33562306a36Sopenharmony_ci if (__test_and_set_bit(i, effect_handled)) 33662306a36Sopenharmony_ci continue; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci state = &ml->states[i]; 33962306a36Sopenharmony_ci effect = state->effect; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (!test_bit(FF_EFFECT_STARTED, &state->flags)) 34262306a36Sopenharmony_ci continue; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (time_before(jiffies, state->play_at)) 34562306a36Sopenharmony_ci continue; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* 34862306a36Sopenharmony_ci * here we have started effects that are either 34962306a36Sopenharmony_ci * currently playing (and may need be aborted) 35062306a36Sopenharmony_ci * or need to start playing. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci effect_type = get_compatible_type(ml->dev->ff, effect->type); 35362306a36Sopenharmony_ci if (combo_effect->type != effect_type) { 35462306a36Sopenharmony_ci if (combo_effect->type != 0) { 35562306a36Sopenharmony_ci __clear_bit(i, effect_handled); 35662306a36Sopenharmony_ci continue; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci combo_effect->type = effect_type; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (__test_and_clear_bit(FF_EFFECT_ABORTING, &state->flags)) { 36262306a36Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 36362306a36Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 36462306a36Sopenharmony_ci } else if (effect->replay.length && 36562306a36Sopenharmony_ci time_after_eq(jiffies, state->stop_at)) { 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (--state->count <= 0) { 37062306a36Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 37162306a36Sopenharmony_ci } else { 37262306a36Sopenharmony_ci state->play_at = jiffies + 37362306a36Sopenharmony_ci msecs_to_jiffies(effect->replay.delay); 37462306a36Sopenharmony_ci state->stop_at = state->play_at + 37562306a36Sopenharmony_ci msecs_to_jiffies(effect->replay.length); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci } else { 37862306a36Sopenharmony_ci __set_bit(FF_EFFECT_PLAYING, &state->flags); 37962306a36Sopenharmony_ci state->adj_at = jiffies; 38062306a36Sopenharmony_ci ml_combine_effects(combo_effect, state, ml->gain); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci return combo_effect->type != 0; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic void ml_play_effects(struct ml_device *ml) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci struct ff_effect effect; 39062306a36Sopenharmony_ci DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci memset(handled_bm, 0, sizeof(handled_bm)); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci while (ml_get_combo_effect(ml, handled_bm, &effect)) 39562306a36Sopenharmony_ci ml->play_effect(ml->dev, ml->private, &effect); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ml_schedule_timer(ml); 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic void ml_effect_timer(struct timer_list *t) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct ml_device *ml = from_timer(ml, t, timer); 40362306a36Sopenharmony_ci struct input_dev *dev = ml->dev; 40462306a36Sopenharmony_ci unsigned long flags; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci pr_debug("timer: updating effects\n"); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci spin_lock_irqsave(&dev->event_lock, flags); 40962306a36Sopenharmony_ci ml_play_effects(ml); 41062306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->event_lock, flags); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/* 41462306a36Sopenharmony_ci * Sets requested gain for FF effects. Called with dev->event_lock held. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_cistatic void ml_ff_set_gain(struct input_dev *dev, u16 gain) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct ml_device *ml = dev->ff->private; 41962306a36Sopenharmony_ci int i; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci ml->gain = gain; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) 42462306a36Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci ml_play_effects(ml); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci/* 43062306a36Sopenharmony_ci * Start/stop specified FF effect. Called with dev->event_lock held. 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_cistatic int ml_ff_playback(struct input_dev *dev, int effect_id, int value) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci struct ml_device *ml = dev->ff->private; 43562306a36Sopenharmony_ci struct ml_effect_state *state = &ml->states[effect_id]; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (value > 0) { 43862306a36Sopenharmony_ci pr_debug("initiated play\n"); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci __set_bit(FF_EFFECT_STARTED, &state->flags); 44162306a36Sopenharmony_ci state->count = value; 44262306a36Sopenharmony_ci state->play_at = jiffies + 44362306a36Sopenharmony_ci msecs_to_jiffies(state->effect->replay.delay); 44462306a36Sopenharmony_ci state->stop_at = state->play_at + 44562306a36Sopenharmony_ci msecs_to_jiffies(state->effect->replay.length); 44662306a36Sopenharmony_ci state->adj_at = state->play_at; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci } else { 44962306a36Sopenharmony_ci pr_debug("initiated stop\n"); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (test_bit(FF_EFFECT_PLAYING, &state->flags)) 45262306a36Sopenharmony_ci __set_bit(FF_EFFECT_ABORTING, &state->flags); 45362306a36Sopenharmony_ci else 45462306a36Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ml_play_effects(ml); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci return 0; 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic int ml_ff_upload(struct input_dev *dev, 46362306a36Sopenharmony_ci struct ff_effect *effect, struct ff_effect *old) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct ml_device *ml = dev->ff->private; 46662306a36Sopenharmony_ci struct ml_effect_state *state = &ml->states[effect->id]; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci spin_lock_irq(&dev->event_lock); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (test_bit(FF_EFFECT_STARTED, &state->flags)) { 47162306a36Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 47262306a36Sopenharmony_ci state->play_at = jiffies + 47362306a36Sopenharmony_ci msecs_to_jiffies(state->effect->replay.delay); 47462306a36Sopenharmony_ci state->stop_at = state->play_at + 47562306a36Sopenharmony_ci msecs_to_jiffies(state->effect->replay.length); 47662306a36Sopenharmony_ci state->adj_at = state->play_at; 47762306a36Sopenharmony_ci ml_schedule_timer(ml); 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci spin_unlock_irq(&dev->event_lock); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return 0; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic void ml_ff_destroy(struct ff_device *ff) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci struct ml_device *ml = ff->private; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* 49062306a36Sopenharmony_ci * Even though we stop all playing effects when tearing down 49162306a36Sopenharmony_ci * an input device (via input_device_flush() that calls into 49262306a36Sopenharmony_ci * input_ff_flush() that stops and erases all effects), we 49362306a36Sopenharmony_ci * do not actually stop the timer, and therefore we should 49462306a36Sopenharmony_ci * do it here. 49562306a36Sopenharmony_ci */ 49662306a36Sopenharmony_ci del_timer_sync(&ml->timer); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci kfree(ml->private); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/** 50262306a36Sopenharmony_ci * input_ff_create_memless() - create memoryless force-feedback device 50362306a36Sopenharmony_ci * @dev: input device supporting force-feedback 50462306a36Sopenharmony_ci * @data: driver-specific data to be passed into @play_effect 50562306a36Sopenharmony_ci * @play_effect: driver-specific method for playing FF effect 50662306a36Sopenharmony_ci */ 50762306a36Sopenharmony_ciint input_ff_create_memless(struct input_dev *dev, void *data, 50862306a36Sopenharmony_ci int (*play_effect)(struct input_dev *, void *, struct ff_effect *)) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct ml_device *ml; 51162306a36Sopenharmony_ci struct ff_device *ff; 51262306a36Sopenharmony_ci int error; 51362306a36Sopenharmony_ci int i; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL); 51662306a36Sopenharmony_ci if (!ml) 51762306a36Sopenharmony_ci return -ENOMEM; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci ml->dev = dev; 52062306a36Sopenharmony_ci ml->private = data; 52162306a36Sopenharmony_ci ml->play_effect = play_effect; 52262306a36Sopenharmony_ci ml->gain = 0xffff; 52362306a36Sopenharmony_ci timer_setup(&ml->timer, ml_effect_timer, 0); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci set_bit(FF_GAIN, dev->ffbit); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci error = input_ff_create(dev, FF_MEMLESS_EFFECTS); 52862306a36Sopenharmony_ci if (error) { 52962306a36Sopenharmony_ci kfree(ml); 53062306a36Sopenharmony_ci return error; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci ff = dev->ff; 53462306a36Sopenharmony_ci ff->private = ml; 53562306a36Sopenharmony_ci ff->upload = ml_ff_upload; 53662306a36Sopenharmony_ci ff->playback = ml_ff_playback; 53762306a36Sopenharmony_ci ff->set_gain = ml_ff_set_gain; 53862306a36Sopenharmony_ci ff->destroy = ml_ff_destroy; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* we can emulate periodic effects with RUMBLE */ 54162306a36Sopenharmony_ci if (test_bit(FF_RUMBLE, ff->ffbit)) { 54262306a36Sopenharmony_ci set_bit(FF_PERIODIC, dev->ffbit); 54362306a36Sopenharmony_ci set_bit(FF_SINE, dev->ffbit); 54462306a36Sopenharmony_ci set_bit(FF_TRIANGLE, dev->ffbit); 54562306a36Sopenharmony_ci set_bit(FF_SQUARE, dev->ffbit); 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) 54962306a36Sopenharmony_ci ml->states[i].effect = &ff->effects[i]; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci return 0; 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(input_ff_create_memless); 554