From 8e881313237d1edd50a5400f8d0ad4957e562807 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Mon, 20 Jul 2015 12:52:17 +0200 Subject: [PATCH] First step towards effect timing implementation. --- klgd_ff_plugin.c | 61 ++++++++++++++++++++++++++++++++++++++++------ klgd_ff_plugin_p.h | 16 ++++++++++-- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/klgd_ff_plugin.c b/klgd_ff_plugin.c index 9151724..00b4666 100644 --- a/klgd_ff_plugin.c +++ b/klgd_ff_plugin.c @@ -1,6 +1,7 @@ #include "klgd_ff_plugin_p.h" #include #include +#include #define DIR_TO_DEGREES(dir) (360 - ((((dir > 0xc000) ? (u32)dir + 0x4000 - 0xffff : (u32)dir + 0x4000) * 360) / 0xffff)) @@ -299,14 +300,26 @@ static int ffpl_playback_rq(struct input_dev *dev, int effect_id, int value) struct klgd_plugin *self = dev->ff->private; struct klgd_plugin_private *priv = self->private; struct ffpl_effect *eff = &priv->effects[effect_id]; + struct ff_effect *uff = &eff->latest; + const unsigned long now = jiffies; klgd_lock_plugins(self->plugins_lock); if (value) { - eff->change = FFPL_TO_START; eff->repeat = value; - } else - eff->change = FFPL_TO_STOP; + eff->start_at = now + msecs_to_jiffies(uff->replay.delay); + eff->trigger = FFPL_TRIG_START; + printk(KERN_NOTICE "KLGDFF: Delayed effect will be started at %lu, now: %lu\n", eff->start_at, now); + + if (uff->replay.length) { + eff->finite = true; + eff->stop_at = eff->start_at + msecs_to_jiffies(uff->replay.length); + printk(KERN_NOTICE "KLGDFF: Finite effect will be stopped at %lu, now: %lu\n", eff->stop_at, now); + } else + eff->finite = false; + } else { + eff->trigger = FFPL_TRIG_STOP; + } klgd_unlock_plugins_sched(self->plugins_lock); @@ -502,19 +515,51 @@ static struct klgd_command_stream * ffpl_get_commands(struct klgd_plugin *self, return s; } +static void ffpl_advance_trigger(struct ffpl_effect *eff) +{ + switch (eff->trigger) { + case FFPL_TRIG_START: + if (eff->finite) + eff->trigger = FFPL_TRIG_STOP; + else + eff->trigger = FFPL_TRIG_NONE; + break; + case FFPL_TRIG_STOP: + eff->trigger = FFPL_TRIG_NONE; + break; + default: + break; + } +} + static bool ffpl_get_update_time(struct klgd_plugin *self, const unsigned long now, unsigned long *t) { struct klgd_plugin_private *priv = self->private; - size_t idx, events = 0; + size_t idx; + unsigned long events = 0; for (idx = 0; idx < priv->effect_count; idx++) { + unsigned long current_t; struct ffpl_effect *eff = &priv->effects[idx]; - /* Tell KLGD to attend to us as soon as possible if an effect has to change state */ - if (eff->change == FFPL_DONT_TOUCH) + switch (eff->trigger) { + default: continue; - *t = now; - events++; + case FFPL_TRIG_START: + current_t = eff->start_at; + eff->change = FFPL_TO_START; + break; + case FFPL_TRIG_STOP: + current_t = eff->stop_at; + eff->change = FFPL_TO_STOP; + break; + } + + ffpl_advance_trigger(eff); + if (!events++) + *t = current_t; + else if (time_before(current_t, *t)) + *t = current_t; } return events ? true : false; diff --git a/klgd_ff_plugin_p.h b/klgd_ff_plugin_p.h index 14e53d8..153f1fb 100644 --- a/klgd_ff_plugin_p.h +++ b/klgd_ff_plugin_p.h @@ -7,7 +7,7 @@ enum ffpl_st_change { FFPL_TO_START, /* Effect shall be started */ FFPL_TO_STOP, /* Effect shall be stopped */ FFPL_TO_ERASE, /* Effect shall be removed from device */ - FFPL_TO_UPDATE /* Effect paramaters shall be updated */ + FFPL_TO_UPDATE, /* Effect paramaters shall be updated */ }; /* Possible states of an effect */ @@ -17,14 +17,26 @@ enum ffpl_state { FFPL_STARTED, /* Effect in the slot is started on device */ }; +/* What to do at the next timing trip point */ +enum ffpl_trigger { + FFPL_TRIG_NONE, /* No timing event scheduled for and effect */ + FFPL_TRIG_START, /* Effect is to be started */ + FFPL_TRIG_STOP /* Effect is to be stopped */ +}; + struct ffpl_effect { struct ff_effect active; /* Last effect submitted to device */ struct ff_effect latest; /* Last effect submitted to us by userspace */ - int repeat; /* How many times to repeat an effect - set in playback_rq */ enum ffpl_st_change change; /* State to which the effect shall be put */ enum ffpl_state state; /* State of the active effect */ bool replace; /* Active effect has to be replaced => active effect shall be erased and latest uploaded */ bool uploaded_to_device; /* Effect was physically uploaded to device */ + + enum ffpl_trigger trigger; /* What to do with the effect at its nearest timing trip point */ + int repeat; /* How many times to repeat an effect - set in playback_rq */ + unsigned long start_at; /* Time when to start the effect - in jiffies */ + unsigned long stop_at; /* Time when to stop the effect - in jiffies */ + bool finite; /* Effect has a finite duration */ }; struct klgd_plugin_private { -- 2.43.5