From 170956ccf84ec072bccd43fcfcd98b4fb00861a9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Tue, 21 Jul 2015 20:08:57 +0200 Subject: [PATCH] Check effect sanity before upload. --- klgd_ff_plugin.c | 65 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/klgd_ff_plugin.c b/klgd_ff_plugin.c index 6ba6fc8..92951e2 100644 --- a/klgd_ff_plugin.c +++ b/klgd_ff_plugin.c @@ -17,6 +17,56 @@ static bool ffpl_is_combinable(const struct ff_effect *eff) return eff->type == FF_CONSTANT; } +static const struct ff_envelope * ffpl_get_envelope(const struct ff_effect *ueff) +{ + switch (ueff->type) { + case FF_CONSTANT: + return &ueff->u.constant.envelope; + case FF_PERIODIC: + return &ueff->u.periodic.envelope; + case FF_RAMP: + return &ueff->u.ramp.envelope; + default: + return NULL; + } +} + +static bool ffpl_is_effect_valid(const struct ff_effect *ueff) +{ + const u16 length = ueff->replay.length; + + /* Periodic effects must have a non-zero period */ + if (ueff->type == FF_PERIODIC) { + if (!ueff->u.periodic.period) + return false; + } + /* Ramp effects cannot be infinite */ + if (ueff->type == FF_RAMP && !length) + return false; + + if (ffpl_is_combinable(ueff)) { + int fade_from; + const struct ff_envelope *env = ffpl_get_envelope(ueff); + + if (!env) + BUG_ON("NULL envelope in effect validity check!"); + + /* Infinite effects cannot fade */ + if (!length && env->fade_length > 0) + return false; + + /* Fade length cannot be greater than effect duration */ + fade_from = (int)length - (int)env->fade_length; + if (fade_from < 0) + return false; + /* Envelope cannot start fading before it finishes attacking */ + if (fade_from < env->attack_length && fade_from > 0) + return false; + } + + return true; +} + static u16 ffpl_atan_int_octet(const u16 x, const u16 y) { u32 result; @@ -342,6 +392,9 @@ static int ffpl_upload_rq(struct input_dev *dev, struct ff_effect *effect, struc struct klgd_plugin_private *priv = self->private; struct ffpl_effect *eff = &priv->effects[effect->id]; + if (!ffpl_is_effect_valid(effect)) + return -EINVAL; + klgd_lock_plugins(self->plugins_lock); spin_lock_irq(&dev->event_lock); @@ -530,18 +583,6 @@ static struct klgd_command_stream * ffpl_get_commands(struct klgd_plugin *self, return s; } -static const struct ff_envelope * ffpl_get_envelope(const struct ff_effect *ueff) -{ - switch (ueff->type) { - case FF_CONSTANT: - return &ueff->u.constant.envelope; - case FF_PERIODIC: - return &ueff->u.periodic.envelope; - default: - return NULL; - } -} - static unsigned long ffpl_get_recalculation_time(const struct ffpl_effect *eff) { unsigned long t_trip; -- 2.43.5