18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Force feedback support for memoryless devices 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> 68c2ecf20Sopenharmony_ci * Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* #define DEBUG */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/input.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/mutex.h> 208c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 218c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 228c2ecf20Sopenharmony_ci#include <linux/fixp-arith.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 258c2ecf20Sopenharmony_ciMODULE_AUTHOR("Anssi Hannula <anssi.hannula@gmail.com>"); 268c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Force feedback support for memoryless devices"); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* Number of effects handled with memoryless devices */ 298c2ecf20Sopenharmony_ci#define FF_MEMLESS_EFFECTS 16 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* Envelope update interval in ms */ 328c2ecf20Sopenharmony_ci#define FF_ENVELOPE_INTERVAL 50 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define FF_EFFECT_STARTED 0 358c2ecf20Sopenharmony_ci#define FF_EFFECT_PLAYING 1 368c2ecf20Sopenharmony_ci#define FF_EFFECT_ABORTING 2 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct ml_effect_state { 398c2ecf20Sopenharmony_ci struct ff_effect *effect; 408c2ecf20Sopenharmony_ci unsigned long flags; /* effect state (STARTED, PLAYING, etc) */ 418c2ecf20Sopenharmony_ci int count; /* loop count of the effect */ 428c2ecf20Sopenharmony_ci unsigned long play_at; /* start time */ 438c2ecf20Sopenharmony_ci unsigned long stop_at; /* stop time */ 448c2ecf20Sopenharmony_ci unsigned long adj_at; /* last time the effect was sent */ 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistruct ml_device { 488c2ecf20Sopenharmony_ci void *private; 498c2ecf20Sopenharmony_ci struct ml_effect_state states[FF_MEMLESS_EFFECTS]; 508c2ecf20Sopenharmony_ci int gain; 518c2ecf20Sopenharmony_ci struct timer_list timer; 528c2ecf20Sopenharmony_ci struct input_dev *dev; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci int (*play_effect)(struct input_dev *dev, void *data, 558c2ecf20Sopenharmony_ci struct ff_effect *effect); 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const struct ff_envelope *get_envelope(const struct ff_effect *effect) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci static const struct ff_envelope empty_envelope; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci switch (effect->type) { 638c2ecf20Sopenharmony_ci case FF_PERIODIC: 648c2ecf20Sopenharmony_ci return &effect->u.periodic.envelope; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci case FF_CONSTANT: 678c2ecf20Sopenharmony_ci return &effect->u.constant.envelope; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci default: 708c2ecf20Sopenharmony_ci return &empty_envelope; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* 758c2ecf20Sopenharmony_ci * Check for the next time envelope requires an update on memoryless devices 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_cistatic unsigned long calculate_next_time(struct ml_effect_state *state) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci const struct ff_envelope *envelope = get_envelope(state->effect); 808c2ecf20Sopenharmony_ci unsigned long attack_stop, fade_start, next_fade; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (envelope->attack_length) { 838c2ecf20Sopenharmony_ci attack_stop = state->play_at + 848c2ecf20Sopenharmony_ci msecs_to_jiffies(envelope->attack_length); 858c2ecf20Sopenharmony_ci if (time_before(state->adj_at, attack_stop)) 868c2ecf20Sopenharmony_ci return state->adj_at + 878c2ecf20Sopenharmony_ci msecs_to_jiffies(FF_ENVELOPE_INTERVAL); 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (state->effect->replay.length) { 918c2ecf20Sopenharmony_ci if (envelope->fade_length) { 928c2ecf20Sopenharmony_ci /* check when fading should start */ 938c2ecf20Sopenharmony_ci fade_start = state->stop_at - 948c2ecf20Sopenharmony_ci msecs_to_jiffies(envelope->fade_length); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (time_before(state->adj_at, fade_start)) 978c2ecf20Sopenharmony_ci return fade_start; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* already fading, advance to next checkpoint */ 1008c2ecf20Sopenharmony_ci next_fade = state->adj_at + 1018c2ecf20Sopenharmony_ci msecs_to_jiffies(FF_ENVELOPE_INTERVAL); 1028c2ecf20Sopenharmony_ci if (time_before(next_fade, state->stop_at)) 1038c2ecf20Sopenharmony_ci return next_fade; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return state->stop_at; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return state->play_at; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void ml_schedule_timer(struct ml_device *ml) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct ml_effect_state *state; 1158c2ecf20Sopenharmony_ci unsigned long now = jiffies; 1168c2ecf20Sopenharmony_ci unsigned long earliest = 0; 1178c2ecf20Sopenharmony_ci unsigned long next_at; 1188c2ecf20Sopenharmony_ci int events = 0; 1198c2ecf20Sopenharmony_ci int i; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci pr_debug("calculating next timer\n"); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci state = &ml->states[i]; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (!test_bit(FF_EFFECT_STARTED, &state->flags)) 1288c2ecf20Sopenharmony_ci continue; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (test_bit(FF_EFFECT_PLAYING, &state->flags)) 1318c2ecf20Sopenharmony_ci next_at = calculate_next_time(state); 1328c2ecf20Sopenharmony_ci else 1338c2ecf20Sopenharmony_ci next_at = state->play_at; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (time_before_eq(now, next_at) && 1368c2ecf20Sopenharmony_ci (++events == 1 || time_before(next_at, earliest))) 1378c2ecf20Sopenharmony_ci earliest = next_at; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (!events) { 1418c2ecf20Sopenharmony_ci pr_debug("no actions\n"); 1428c2ecf20Sopenharmony_ci del_timer(&ml->timer); 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci pr_debug("timer set\n"); 1458c2ecf20Sopenharmony_ci mod_timer(&ml->timer, earliest); 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * Apply an envelope to a value 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic int apply_envelope(struct ml_effect_state *state, int value, 1538c2ecf20Sopenharmony_ci struct ff_envelope *envelope) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct ff_effect *effect = state->effect; 1568c2ecf20Sopenharmony_ci unsigned long now = jiffies; 1578c2ecf20Sopenharmony_ci int time_from_level; 1588c2ecf20Sopenharmony_ci int time_of_envelope; 1598c2ecf20Sopenharmony_ci int envelope_level; 1608c2ecf20Sopenharmony_ci int difference; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (envelope->attack_length && 1638c2ecf20Sopenharmony_ci time_before(now, 1648c2ecf20Sopenharmony_ci state->play_at + msecs_to_jiffies(envelope->attack_length))) { 1658c2ecf20Sopenharmony_ci pr_debug("value = 0x%x, attack_level = 0x%x\n", 1668c2ecf20Sopenharmony_ci value, envelope->attack_level); 1678c2ecf20Sopenharmony_ci time_from_level = jiffies_to_msecs(now - state->play_at); 1688c2ecf20Sopenharmony_ci time_of_envelope = envelope->attack_length; 1698c2ecf20Sopenharmony_ci envelope_level = min_t(u16, envelope->attack_level, 0x7fff); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci } else if (envelope->fade_length && effect->replay.length && 1728c2ecf20Sopenharmony_ci time_after(now, 1738c2ecf20Sopenharmony_ci state->stop_at - msecs_to_jiffies(envelope->fade_length)) && 1748c2ecf20Sopenharmony_ci time_before(now, state->stop_at)) { 1758c2ecf20Sopenharmony_ci time_from_level = jiffies_to_msecs(state->stop_at - now); 1768c2ecf20Sopenharmony_ci time_of_envelope = envelope->fade_length; 1778c2ecf20Sopenharmony_ci envelope_level = min_t(u16, envelope->fade_level, 0x7fff); 1788c2ecf20Sopenharmony_ci } else 1798c2ecf20Sopenharmony_ci return value; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci difference = abs(value) - envelope_level; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci pr_debug("difference = %d\n", difference); 1848c2ecf20Sopenharmony_ci pr_debug("time_from_level = 0x%x\n", time_from_level); 1858c2ecf20Sopenharmony_ci pr_debug("time_of_envelope = 0x%x\n", time_of_envelope); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci difference = difference * time_from_level / time_of_envelope; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci pr_debug("difference = %d\n", difference); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return value < 0 ? 1928c2ecf20Sopenharmony_ci -(difference + envelope_level) : (difference + envelope_level); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* 1968c2ecf20Sopenharmony_ci * Return the type the effect has to be converted into (memless devices) 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_cistatic int get_compatible_type(struct ff_device *ff, int effect_type) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (test_bit(effect_type, ff->ffbit)) 2028c2ecf20Sopenharmony_ci return effect_type; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) 2058c2ecf20Sopenharmony_ci return FF_RUMBLE; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci pr_err("invalid type in get_compatible_type()\n"); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return 0; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* 2138c2ecf20Sopenharmony_ci * Only left/right direction should be used (under/over 0x8000) for 2148c2ecf20Sopenharmony_ci * forward/reverse motor direction (to keep calculation fast & simple). 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_cistatic u16 ml_calculate_direction(u16 direction, u16 force, 2178c2ecf20Sopenharmony_ci u16 new_direction, u16 new_force) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci if (!force) 2208c2ecf20Sopenharmony_ci return new_direction; 2218c2ecf20Sopenharmony_ci if (!new_force) 2228c2ecf20Sopenharmony_ci return direction; 2238c2ecf20Sopenharmony_ci return (((u32)(direction >> 1) * force + 2248c2ecf20Sopenharmony_ci (new_direction >> 1) * new_force) / 2258c2ecf20Sopenharmony_ci (force + new_force)) << 1; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define FRAC_N 8 2298c2ecf20Sopenharmony_cistatic inline s16 fixp_new16(s16 a) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci return ((s32)a) >> (16 - FRAC_N); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic inline s16 fixp_mult(s16 a, s16 b) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci a = ((s32)a * 0x100) / 0x7fff; 2378c2ecf20Sopenharmony_ci return ((s32)(a * b)) >> FRAC_N; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* 2418c2ecf20Sopenharmony_ci * Combine two effects and apply gain. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_cistatic void ml_combine_effects(struct ff_effect *effect, 2448c2ecf20Sopenharmony_ci struct ml_effect_state *state, 2458c2ecf20Sopenharmony_ci int gain) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci struct ff_effect *new = state->effect; 2488c2ecf20Sopenharmony_ci unsigned int strong, weak, i; 2498c2ecf20Sopenharmony_ci int x, y; 2508c2ecf20Sopenharmony_ci s16 level; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci switch (new->type) { 2538c2ecf20Sopenharmony_ci case FF_CONSTANT: 2548c2ecf20Sopenharmony_ci i = new->direction * 360 / 0xffff; 2558c2ecf20Sopenharmony_ci level = fixp_new16(apply_envelope(state, 2568c2ecf20Sopenharmony_ci new->u.constant.level, 2578c2ecf20Sopenharmony_ci &new->u.constant.envelope)); 2588c2ecf20Sopenharmony_ci x = fixp_mult(fixp_sin16(i), level) * gain / 0xffff; 2598c2ecf20Sopenharmony_ci y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff; 2608c2ecf20Sopenharmony_ci /* 2618c2ecf20Sopenharmony_ci * here we abuse ff_ramp to hold x and y of constant force 2628c2ecf20Sopenharmony_ci * If in future any driver wants something else than x and y 2638c2ecf20Sopenharmony_ci * in s8, this should be changed to something more generic 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ci effect->u.ramp.start_level = 2668c2ecf20Sopenharmony_ci clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f); 2678c2ecf20Sopenharmony_ci effect->u.ramp.end_level = 2688c2ecf20Sopenharmony_ci clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f); 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci case FF_RUMBLE: 2728c2ecf20Sopenharmony_ci strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; 2738c2ecf20Sopenharmony_ci weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (effect->u.rumble.strong_magnitude + strong) 2768c2ecf20Sopenharmony_ci effect->direction = ml_calculate_direction( 2778c2ecf20Sopenharmony_ci effect->direction, 2788c2ecf20Sopenharmony_ci effect->u.rumble.strong_magnitude, 2798c2ecf20Sopenharmony_ci new->direction, strong); 2808c2ecf20Sopenharmony_ci else if (effect->u.rumble.weak_magnitude + weak) 2818c2ecf20Sopenharmony_ci effect->direction = ml_calculate_direction( 2828c2ecf20Sopenharmony_ci effect->direction, 2838c2ecf20Sopenharmony_ci effect->u.rumble.weak_magnitude, 2848c2ecf20Sopenharmony_ci new->direction, weak); 2858c2ecf20Sopenharmony_ci else 2868c2ecf20Sopenharmony_ci effect->direction = 0; 2878c2ecf20Sopenharmony_ci effect->u.rumble.strong_magnitude = 2888c2ecf20Sopenharmony_ci min(strong + effect->u.rumble.strong_magnitude, 2898c2ecf20Sopenharmony_ci 0xffffU); 2908c2ecf20Sopenharmony_ci effect->u.rumble.weak_magnitude = 2918c2ecf20Sopenharmony_ci min(weak + effect->u.rumble.weak_magnitude, 0xffffU); 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci case FF_PERIODIC: 2958c2ecf20Sopenharmony_ci i = apply_envelope(state, abs(new->u.periodic.magnitude), 2968c2ecf20Sopenharmony_ci &new->u.periodic.envelope); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* here we also scale it 0x7fff => 0xffff */ 2998c2ecf20Sopenharmony_ci i = i * gain / 0x7fff; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (effect->u.rumble.strong_magnitude + i) 3028c2ecf20Sopenharmony_ci effect->direction = ml_calculate_direction( 3038c2ecf20Sopenharmony_ci effect->direction, 3048c2ecf20Sopenharmony_ci effect->u.rumble.strong_magnitude, 3058c2ecf20Sopenharmony_ci new->direction, i); 3068c2ecf20Sopenharmony_ci else 3078c2ecf20Sopenharmony_ci effect->direction = 0; 3088c2ecf20Sopenharmony_ci effect->u.rumble.strong_magnitude = 3098c2ecf20Sopenharmony_ci min(i + effect->u.rumble.strong_magnitude, 0xffffU); 3108c2ecf20Sopenharmony_ci effect->u.rumble.weak_magnitude = 3118c2ecf20Sopenharmony_ci min(i + effect->u.rumble.weak_magnitude, 0xffffU); 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci default: 3158c2ecf20Sopenharmony_ci pr_err("invalid type in ml_combine_effects()\n"); 3168c2ecf20Sopenharmony_ci break; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/* 3238c2ecf20Sopenharmony_ci * Because memoryless devices have only one effect per effect type active 3248c2ecf20Sopenharmony_ci * at one time we have to combine multiple effects into one 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_cistatic int ml_get_combo_effect(struct ml_device *ml, 3278c2ecf20Sopenharmony_ci unsigned long *effect_handled, 3288c2ecf20Sopenharmony_ci struct ff_effect *combo_effect) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci struct ff_effect *effect; 3318c2ecf20Sopenharmony_ci struct ml_effect_state *state; 3328c2ecf20Sopenharmony_ci int effect_type; 3338c2ecf20Sopenharmony_ci int i; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci memset(combo_effect, 0, sizeof(struct ff_effect)); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { 3388c2ecf20Sopenharmony_ci if (__test_and_set_bit(i, effect_handled)) 3398c2ecf20Sopenharmony_ci continue; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci state = &ml->states[i]; 3428c2ecf20Sopenharmony_ci effect = state->effect; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci if (!test_bit(FF_EFFECT_STARTED, &state->flags)) 3458c2ecf20Sopenharmony_ci continue; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (time_before(jiffies, state->play_at)) 3488c2ecf20Sopenharmony_ci continue; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* 3518c2ecf20Sopenharmony_ci * here we have started effects that are either 3528c2ecf20Sopenharmony_ci * currently playing (and may need be aborted) 3538c2ecf20Sopenharmony_ci * or need to start playing. 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci effect_type = get_compatible_type(ml->dev->ff, effect->type); 3568c2ecf20Sopenharmony_ci if (combo_effect->type != effect_type) { 3578c2ecf20Sopenharmony_ci if (combo_effect->type != 0) { 3588c2ecf20Sopenharmony_ci __clear_bit(i, effect_handled); 3598c2ecf20Sopenharmony_ci continue; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci combo_effect->type = effect_type; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (__test_and_clear_bit(FF_EFFECT_ABORTING, &state->flags)) { 3658c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 3668c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 3678c2ecf20Sopenharmony_ci } else if (effect->replay.length && 3688c2ecf20Sopenharmony_ci time_after_eq(jiffies, state->stop_at)) { 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (--state->count <= 0) { 3738c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 3748c2ecf20Sopenharmony_ci } else { 3758c2ecf20Sopenharmony_ci state->play_at = jiffies + 3768c2ecf20Sopenharmony_ci msecs_to_jiffies(effect->replay.delay); 3778c2ecf20Sopenharmony_ci state->stop_at = state->play_at + 3788c2ecf20Sopenharmony_ci msecs_to_jiffies(effect->replay.length); 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci } else { 3818c2ecf20Sopenharmony_ci __set_bit(FF_EFFECT_PLAYING, &state->flags); 3828c2ecf20Sopenharmony_ci state->adj_at = jiffies; 3838c2ecf20Sopenharmony_ci ml_combine_effects(combo_effect, state, ml->gain); 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci return combo_effect->type != 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic void ml_play_effects(struct ml_device *ml) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct ff_effect effect; 3938c2ecf20Sopenharmony_ci DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci memset(handled_bm, 0, sizeof(handled_bm)); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci while (ml_get_combo_effect(ml, handled_bm, &effect)) 3988c2ecf20Sopenharmony_ci ml->play_effect(ml->dev, ml->private, &effect); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci ml_schedule_timer(ml); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic void ml_effect_timer(struct timer_list *t) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci struct ml_device *ml = from_timer(ml, t, timer); 4068c2ecf20Sopenharmony_ci struct input_dev *dev = ml->dev; 4078c2ecf20Sopenharmony_ci unsigned long flags; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci pr_debug("timer: updating effects\n"); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->event_lock, flags); 4128c2ecf20Sopenharmony_ci ml_play_effects(ml); 4138c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->event_lock, flags); 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci/* 4178c2ecf20Sopenharmony_ci * Sets requested gain for FF effects. Called with dev->event_lock held. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_cistatic void ml_ff_set_gain(struct input_dev *dev, u16 gain) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct ml_device *ml = dev->ff->private; 4228c2ecf20Sopenharmony_ci int i; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci ml->gain = gain; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) 4278c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci ml_play_effects(ml); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/* 4338c2ecf20Sopenharmony_ci * Start/stop specified FF effect. Called with dev->event_lock held. 4348c2ecf20Sopenharmony_ci */ 4358c2ecf20Sopenharmony_cistatic int ml_ff_playback(struct input_dev *dev, int effect_id, int value) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci struct ml_device *ml = dev->ff->private; 4388c2ecf20Sopenharmony_ci struct ml_effect_state *state = &ml->states[effect_id]; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (value > 0) { 4418c2ecf20Sopenharmony_ci pr_debug("initiated play\n"); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci __set_bit(FF_EFFECT_STARTED, &state->flags); 4448c2ecf20Sopenharmony_ci state->count = value; 4458c2ecf20Sopenharmony_ci state->play_at = jiffies + 4468c2ecf20Sopenharmony_ci msecs_to_jiffies(state->effect->replay.delay); 4478c2ecf20Sopenharmony_ci state->stop_at = state->play_at + 4488c2ecf20Sopenharmony_ci msecs_to_jiffies(state->effect->replay.length); 4498c2ecf20Sopenharmony_ci state->adj_at = state->play_at; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci } else { 4528c2ecf20Sopenharmony_ci pr_debug("initiated stop\n"); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (test_bit(FF_EFFECT_PLAYING, &state->flags)) 4558c2ecf20Sopenharmony_ci __set_bit(FF_EFFECT_ABORTING, &state->flags); 4568c2ecf20Sopenharmony_ci else 4578c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_STARTED, &state->flags); 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci ml_play_effects(ml); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return 0; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic int ml_ff_upload(struct input_dev *dev, 4668c2ecf20Sopenharmony_ci struct ff_effect *effect, struct ff_effect *old) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct ml_device *ml = dev->ff->private; 4698c2ecf20Sopenharmony_ci struct ml_effect_state *state = &ml->states[effect->id]; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci spin_lock_irq(&dev->event_lock); 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci if (test_bit(FF_EFFECT_STARTED, &state->flags)) { 4748c2ecf20Sopenharmony_ci __clear_bit(FF_EFFECT_PLAYING, &state->flags); 4758c2ecf20Sopenharmony_ci state->play_at = jiffies + 4768c2ecf20Sopenharmony_ci msecs_to_jiffies(state->effect->replay.delay); 4778c2ecf20Sopenharmony_ci state->stop_at = state->play_at + 4788c2ecf20Sopenharmony_ci msecs_to_jiffies(state->effect->replay.length); 4798c2ecf20Sopenharmony_ci state->adj_at = state->play_at; 4808c2ecf20Sopenharmony_ci ml_schedule_timer(ml); 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci spin_unlock_irq(&dev->event_lock); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci return 0; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic void ml_ff_destroy(struct ff_device *ff) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci struct ml_device *ml = ff->private; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci /* 4938c2ecf20Sopenharmony_ci * Even though we stop all playing effects when tearing down 4948c2ecf20Sopenharmony_ci * an input device (via input_device_flush() that calls into 4958c2ecf20Sopenharmony_ci * input_ff_flush() that stops and erases all effects), we 4968c2ecf20Sopenharmony_ci * do not actually stop the timer, and therefore we should 4978c2ecf20Sopenharmony_ci * do it here. 4988c2ecf20Sopenharmony_ci */ 4998c2ecf20Sopenharmony_ci del_timer_sync(&ml->timer); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci kfree(ml->private); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci/** 5058c2ecf20Sopenharmony_ci * input_ff_create_memless() - create memoryless force-feedback device 5068c2ecf20Sopenharmony_ci * @dev: input device supporting force-feedback 5078c2ecf20Sopenharmony_ci * @data: driver-specific data to be passed into @play_effect 5088c2ecf20Sopenharmony_ci * @play_effect: driver-specific method for playing FF effect 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_ciint input_ff_create_memless(struct input_dev *dev, void *data, 5118c2ecf20Sopenharmony_ci int (*play_effect)(struct input_dev *, void *, struct ff_effect *)) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci struct ml_device *ml; 5148c2ecf20Sopenharmony_ci struct ff_device *ff; 5158c2ecf20Sopenharmony_ci int error; 5168c2ecf20Sopenharmony_ci int i; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL); 5198c2ecf20Sopenharmony_ci if (!ml) 5208c2ecf20Sopenharmony_ci return -ENOMEM; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci ml->dev = dev; 5238c2ecf20Sopenharmony_ci ml->private = data; 5248c2ecf20Sopenharmony_ci ml->play_effect = play_effect; 5258c2ecf20Sopenharmony_ci ml->gain = 0xffff; 5268c2ecf20Sopenharmony_ci timer_setup(&ml->timer, ml_effect_timer, 0); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci set_bit(FF_GAIN, dev->ffbit); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci error = input_ff_create(dev, FF_MEMLESS_EFFECTS); 5318c2ecf20Sopenharmony_ci if (error) { 5328c2ecf20Sopenharmony_ci kfree(ml); 5338c2ecf20Sopenharmony_ci return error; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci ff = dev->ff; 5378c2ecf20Sopenharmony_ci ff->private = ml; 5388c2ecf20Sopenharmony_ci ff->upload = ml_ff_upload; 5398c2ecf20Sopenharmony_ci ff->playback = ml_ff_playback; 5408c2ecf20Sopenharmony_ci ff->set_gain = ml_ff_set_gain; 5418c2ecf20Sopenharmony_ci ff->destroy = ml_ff_destroy; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* we can emulate periodic effects with RUMBLE */ 5448c2ecf20Sopenharmony_ci if (test_bit(FF_RUMBLE, ff->ffbit)) { 5458c2ecf20Sopenharmony_ci set_bit(FF_PERIODIC, dev->ffbit); 5468c2ecf20Sopenharmony_ci set_bit(FF_SINE, dev->ffbit); 5478c2ecf20Sopenharmony_ci set_bit(FF_TRIANGLE, dev->ffbit); 5488c2ecf20Sopenharmony_ci set_bit(FF_SQUARE, dev->ffbit); 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci for (i = 0; i < FF_MEMLESS_EFFECTS; i++) 5528c2ecf20Sopenharmony_ci ml->states[i].effect = &ff->effects[i]; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(input_ff_create_memless); 557