* [RFC] ForceFeedback sequences
@ 2010-02-10 9:03 Jari Vanhala
0 siblings, 0 replies; only message in thread
From: Jari Vanhala @ 2010-02-10 9:03 UTC (permalink / raw)
To: Linux Input
[-- Attachment #1: Type: text/plain, Size: 736 bytes --]
Linux FF-interface hasn't developed much. How about adding sequences to
that interface.
Here is small test-patch which I made to look what kind of problems
there might be. This is ff-memless only because I wanted to reuse it's
timer system. Also, it's not optimized (kind of ugly hack :). Anyway, it
shows some problematic things, like custom_data pointer state, ownership
of effect and is effect still enabled. Moving to ff-core solves most of
these.
More generic way to do this would be at ff-core, so all ff-devices could
use it, but thats not a simple task (timers..). Also kind of misusing
custom-field is probably not so good thing :). Maybe adding new type or
something.
So, what you think? Does this make any sense?
++Jam
[-- Attachment #2: 0001-Input-FF-memless-custom-sequence-hack.patch --]
[-- Type: text/x-patch, Size: 7448 bytes --]
>From dec8a86ff4b287019b4ce6989a738934c9eb95a1 Mon Sep 17 00:00:00 2001
From: Jari Vanhala <ext-jari.vanhala@nokia.com>
Date: Tue, 9 Feb 2010 11:03:54 +0200
Subject: [PATCH] Input: FF-memless custom sequence hack
This takes unused custom functionality and use it for
making sequences in ff-memless. This can be only counted
as a hack for testing purposes.
Signed-off-by: Jari Vanhala <ext-jari.vanhala@nokia.com>
---
drivers/input/ff-core.c | 9 +++
drivers/input/ff-memless.c | 115 ++++++++++++++++++++++++++++++++++++++++-
drivers/input/input-compat.c | 1 +
3 files changed, 122 insertions(+), 3 deletions(-)
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 59797a3..6396328 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -193,6 +193,9 @@ static int erase_effect(struct input_dev *dev, int effect_id,
return error;
spin_lock_irq(&dev->event_lock);
+ if (ff->effects[effect_id].type == FF_PERIODIC &&
+ ff->effects[effect_id].u.periodic.waveform == FF_CUSTOM)
+ ff->effects[effect_id].u.periodic.custom_data = NULL;
ff->playback(dev, effect_id, 0);
ff->effect_owners[effect_id] = NULL;
spin_unlock_irq(&dev->event_lock);
@@ -250,6 +253,12 @@ static int flush_effects(struct input_dev *dev, struct file *file)
mutex_lock(&ff->mutex);
for (i = 0; i < ff->max_effects; i++)
+ if (!check_effect_access(ff, i, file) &&
+ ff->effects[i].type == FF_PERIODIC &&
+ ff->effects[i].u.periodic.waveform == FF_CUSTOM)
+ ff->effects[i].u.periodic.custom_data = NULL;
+
+ for (i = 0; i < ff->max_effects; i++)
erase_effect(dev, i, file);
mutex_unlock(&ff->mutex);
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index f967008..b14510b 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -54,6 +54,7 @@ struct ml_effect_state {
unsigned long play_at; /* start time */
unsigned long stop_at; /* stop time */
unsigned long adj_at; /* last time the effect was sent */
+ int custom_index; /* current custom index */
};
struct ml_device {
@@ -317,6 +318,29 @@ static void ml_combine_effects(struct ff_effect *effect,
}
+#define IS_CUSTOM(effect) (effect->type == FF_PERIODIC && \
+ effect->u.periodic.waveform == FF_CUSTOM)
+static struct ff_effect *find_custom_effect(struct ml_effect_state *states,
+ struct ff_effect *effect,
+ int index)
+{
+ s16 id;
+ struct ff_effect *ret;
+
+ if (!effect || !effect->u.periodic.custom_data ||
+ effect->u.periodic.custom_len / sizeof(__s16) <= index)
+ return NULL;
+ /* XXX: check if effect->u.periodic.custom_data still points
+ * to valid memory */
+ id = effect->u.periodic.custom_data[index];
+ if (id < 0 || id == effect->id || id >= FF_MEMLESS_EFFECTS)
+ return NULL;
+ ret = states[id].effect;
+ if (IS_CUSTOM(ret))
+ return NULL;
+
+ return ret;
+}
/*
* Because memoryless devices have only one effect per effect type active
@@ -326,7 +350,7 @@ static int ml_get_combo_effect(struct ml_device *ml,
unsigned long *effect_handled,
struct ff_effect *combo_effect)
{
- struct ff_effect *effect;
+ struct ff_effect *effect, *effect2;
struct ml_effect_state *state;
int effect_type;
int i;
@@ -368,9 +392,56 @@ static int ml_get_combo_effect(struct ml_device *ml,
__clear_bit(FF_EFFECT_PLAYING, &state->flags);
+ if (IS_CUSTOM(effect)) {
+ state->custom_index++;
+ effect2 = find_custom_effect(ml->states,
+ effect, state->custom_index);
+ if (effect2) {
+ struct ff_envelope *envelope;
+ state->play_at = jiffies +
+ msecs_to_jiffies(effect2->
+ replay.delay);
+ state->stop_at = state->play_at +
+ msecs_to_jiffies(effect2->
+ replay.length);
+ state->adj_at = state->play_at;
+ effect->replay.length =
+ effect2->replay.length;
+ envelope = (struct ff_envelope *)
+ get_envelope(effect2);
+ effect->u.periodic.envelope =
+ *envelope;
+ __clear_bit(i, effect_handled);
+ i--;
+ continue;
+ }
+ }
+
if (--state->count <= 0) {
__clear_bit(FF_EFFECT_STARTED, &state->flags);
} else {
+ if (IS_CUSTOM(effect)) {
+ struct ff_envelope *envelope;
+ state->custom_index = 0;
+ effect2 =
+ find_custom_effect(ml->states,
+ effect, state->custom_index);
+ if (!effect2) {
+ __clear_bit(FF_EFFECT_PLAYING,
+ &state->flags);
+ __clear_bit(FF_EFFECT_STARTED,
+ &state->flags);
+ continue;
+ }
+ effect->replay.length =
+ effect2->replay.length;
+ envelope = (struct ff_envelope *)
+ get_envelope(effect2);
+ effect->u.periodic.envelope =
+ *envelope;
+ __clear_bit(i, effect_handled);
+ i--;
+ }
state->play_at = jiffies +
msecs_to_jiffies(effect->replay.delay);
state->stop_at = state->play_at +
@@ -378,8 +449,27 @@ static int ml_get_combo_effect(struct ml_device *ml,
}
} else {
__set_bit(FF_EFFECT_PLAYING, &state->flags);
- state->adj_at = jiffies;
- ml_combine_effects(combo_effect, state, ml->gain);
+ if (IS_CUSTOM(effect)) {
+ struct ml_effect_state state2;
+ effect2 = find_custom_effect(ml->states,
+ effect, state->custom_index);
+ if (!effect2) {
+ __clear_bit(FF_EFFECT_PLAYING,
+ &state->flags);
+ __clear_bit(FF_EFFECT_STARTED,
+ &state->flags);
+ continue;
+ }
+ state->adj_at = jiffies;
+ memcpy(&state2, state, sizeof(state2));
+ state2.effect = effect2;
+ ml_combine_effects(combo_effect,
+ &state2, ml->gain);
+ } else {
+ state->adj_at = jiffies;
+ ml_combine_effects(combo_effect, state,
+ ml->gain);
+ }
}
}
@@ -446,6 +536,24 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
state->stop_at = state->play_at +
msecs_to_jiffies(state->effect->replay.length);
state->adj_at = state->play_at;
+ if (IS_CUSTOM(state->effect)) {
+ struct ff_effect *effect;
+ struct ff_envelope *envelope;
+ state->custom_index = 0;
+ effect = find_custom_effect(ml->states, state->effect,
+ state->custom_index);
+ if (!effect) {
+ __clear_bit(FF_EFFECT_STARTED, &state->flags);
+ return -EINVAL;
+ }
+ state->play_at = jiffies +
+ msecs_to_jiffies(effect->replay.delay);
+ state->stop_at = state->play_at +
+ msecs_to_jiffies(effect->replay.length);
+ state->effect->replay.length = effect->replay.length;
+ envelope = (struct ff_envelope *)get_envelope(effect);
+ state->effect->u.periodic.envelope = *envelope;
+ }
} else {
debug("initiated stop");
@@ -536,6 +644,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
set_bit(FF_SINE, dev->ffbit);
set_bit(FF_TRIANGLE, dev->ffbit);
set_bit(FF_SQUARE, dev->ffbit);
+ set_bit(FF_CUSTOM, dev->ffbit);
}
for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
diff --git a/drivers/input/input-compat.c b/drivers/input/input-compat.c
index 1accb89..2df00b6 100644
--- a/drivers/input/input-compat.c
+++ b/drivers/input/input-compat.c
@@ -83,6 +83,7 @@ int input_ff_effect_from_user(const char __user *buffer, size_t size,
if (compat_effect->type == FF_PERIODIC &&
compat_effect->u.periodic.waveform == FF_CUSTOM)
+ /* This propably should make a real copy ++Jam */
effect->u.periodic.custom_data =
compat_ptr(compat_effect->u.periodic.custom_data);
} else {
--
1.6.3.3
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2010-02-10 9:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-10 9:03 [RFC] ForceFeedback sequences Jari Vanhala
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).