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