]> Devoid-pointer.net GitWeb - KLGD_FF_plugin.git/commitdiff
- Adapt to KLGD's updated API
authorMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 23:10:25 +0000 (01:10 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 23:10:25 +0000 (01:10 +0200)
- Add actual support for adjustable gain

klgd_ff_plugin.c
klgd_ff_plugin.h
klgd_ff_plugin_p.h
klgdff.c

index e741d421304aea1f943c8ff7a9793021daea31e0..9e01c91bd810182a100bec7c316155fd058d403b 100644 (file)
@@ -9,7 +9,6 @@
 
 static int ffpl_handle_state_change(struct klgd_plugin_private *priv, struct klgd_command_stream *s, struct ffpl_effect *eff,
                                    const unsigned long now);
-static bool ffpl_has_gain(const struct ff_effect *eff);
 static bool ffpl_needs_replacing(const struct ff_effect *ac_eff, const struct ff_effect *la_eff);
 
 void ffpl_lvl_dir_to_x_y(const s32 level, const u16 direction, s32 *x, s32 *y)
@@ -496,6 +495,14 @@ static int ffpl_upload_effect(struct klgd_plugin_private *priv, struct klgd_comm
        return 0;
 }
 
+static int ffpl_set_gain(struct klgd_plugin_private *priv, struct klgd_command_stream *s)
+{
+       union ffpl_control_data data;
+
+       data.gain = priv->gain;
+       return priv->control(priv->dev, s, FFPL_SET_GAIN, data);
+}
+
 static void ffpl_calculate_trip_times(struct ffpl_effect *eff, const unsigned long now)
 {
        const struct ff_effect *ueff = &eff->latest;
@@ -603,7 +610,6 @@ static int ffpl_upload_rq(struct input_dev *dev, struct ff_effect *effect, struc
        return 0;
 }
 
-/*FIXME: Rewrite this! */
 static void ffpl_set_gain_rq(struct input_dev *dev, u16 gain)
 {
        struct klgd_plugin *self = dev->ff->private;
@@ -612,15 +618,22 @@ static void ffpl_set_gain_rq(struct input_dev *dev, u16 gain)
 
        klgd_lock_plugins(self->plugins_lock);
 
-       printk(KERN_DEBUG "KLGDFF: Gain set, %u\n", gain);
+       priv->gain = gain;
+       priv->change_gain = true;
+       if (priv->has_native_gain)
+               goto out;
+
        for (idx = 0; idx < priv->effect_count; idx++) {
                struct ffpl_effect *eff = &priv->effects[idx];
 
-               if (ffpl_has_gain(&eff->active))
-                       eff->change = FFPL_TO_UPDATE;
+               if (eff->state != FFPL_STARTED)
+                       continue;
+
+               eff->change = FFPL_TO_UPDATE;
+               eff->trigger = FFPL_TRIG_NOW;
        }
-       /* priv->gain = gain;*/
 
+out:
        klgd_unlock_plugins_sched(self->plugins_lock);
 }
 
@@ -896,40 +909,52 @@ static void ffpl_advance_trigger(struct ffpl_effect *eff, const unsigned long no
        }
 }
 
-static struct klgd_command_stream * ffpl_get_commands(struct klgd_plugin *self, const unsigned long now)
+static int ffpl_get_commands(struct klgd_plugin *self, struct klgd_command_stream **s, const unsigned long now)
 {
        struct klgd_plugin_private *priv = self->private;
-       struct klgd_command_stream *s;
        size_t idx;
        int ret;
 
-       s = klgd_alloc_stream();
+       *s = klgd_alloc_stream();
        if (!s)
-               return NULL; /* TODO: Error handling */
+               return -EAGAIN;
 
-       ret = ffpl_handle_combinable_effects(priv, s, now);
-       if (ret)
+       if (priv->change_gain) {
+               ret = ffpl_set_gain(priv, *s);
+               if (ret)
+                       goto out;
+               priv->change_gain = false;
+       }
+
+       ret = ffpl_handle_combinable_effects(priv, *s, now);
+       if (ret) {
                printk(KERN_WARNING "KLGDFF: Cannot process combinable effects, ret %d\n", ret);
+               goto out;
+       }
 
        /* Handle combined effect here */
-       ret = ffpl_handle_state_change(priv, s, &priv->combined_effect, now);
-       if (ret)
+       ret = ffpl_handle_state_change(priv, *s, &priv->combined_effect, now);
+       if (ret) {
                printk(KERN_WARNING "KLGDFF: Cannot get command stream for combined effect\n");
+               goto out;
+       }
 
        for (idx = 0; idx < priv->effect_count; idx++) {
                struct ffpl_effect *eff = &priv->effects[idx];
 
                printk(KERN_NOTICE "KLGDFF: Processing effect %lu\n", idx);
-               ret = ffpl_handle_state_change(priv, s, eff, now);
+               ret = ffpl_handle_state_change(priv, *s, eff, now);
                /* TODO: Do something useful with the return code */
-               if (ret)
+               if (ret) {
                        printk(KERN_WARNING "KLGDFF: Cannot get command stream for effect %lu\n", idx);
+                       goto out;
+               }
 
                ffpl_advance_trigger(eff, now);
        }
 
-
-       return s;
+out:
+       return ret;
 }
 
 static bool ffpl_get_update_time(struct klgd_plugin *self, const unsigned long now, unsigned long *t)
@@ -938,6 +963,12 @@ static bool ffpl_get_update_time(struct klgd_plugin *self, const unsigned long n
        size_t idx;
        unsigned long events = 0;
 
+       /* Handle device-wide changes first */
+       if (priv->change_gain) {
+               *t = now;
+               return true;
+       }
+
        for (idx = 0; idx < priv->effect_count; idx++) {
                unsigned long current_t;
                struct ffpl_effect *eff = &priv->effects[idx];
@@ -1165,19 +1196,6 @@ static int ffpl_handle_state_change(struct klgd_plugin_private *priv, struct klg
        return ret;
 }
 
-static bool ffpl_has_gain(const struct ff_effect *eff)
-{
-       switch (eff->type) {
-       case FF_CONSTANT:
-        case FF_PERIODIC:
-       case FF_RAMP:
-       case FF_RUMBLE:
-               return true;
-       default:
-               return false;
-       }
-}
-
 static int ffpl_init(struct klgd_plugin *self)
 {
        struct klgd_plugin_private *priv = self->private;
@@ -1239,6 +1257,7 @@ int ffpl_init_plugin(struct klgd_plugin **plugin, struct input_dev *dev, const s
        priv->effect_count = effect_count;
        priv->dev = dev;
        priv->control = control;
+       priv->gain = 0xFFFF;
 
        self->private = priv;
        *plugin = self;
@@ -1269,6 +1288,10 @@ int ffpl_init_plugin(struct klgd_plugin **plugin, struct input_dev *dev, const s
                priv->has_owr_to_srt = true;
                printk("KLGDFF: Using REPLACE STARTED\n");
        }
+       if (FFPL_HAS_NATIVE_GAIN & flags) {
+               priv->has_native_gain = true;
+               printk(KERN_NOTICE "KLGDFF: Using HAS_NATIVE_GAIN\n");
+       }
 
        set_bit(FF_GAIN, dev->ffbit);
        for (idx = 0; idx <= (FF_WAVEFORM_MAX - FF_EFFECT_MIN); idx++) {
index e77f8558154f9cd0dc611f941c41249355271a3d..aee737804c9987f031450d3d00b995602883fc8b 100644 (file)
@@ -10,6 +10,7 @@
 #define FFPL_ERASE_WHEN_STOPPED BIT(3) /* Erases effect from device when it is stopped - this implies HAS_SRT_TO_EMP */
 #define FFPL_REPLACE_UPLOADED BIT(4) /* Device can accept a new effect to UPLOADED state without the need to explicitly stop and erase the previously uploaded effect beforehand */
 #define FFPL_REPLACE_STARTED BIT(5) /* Device can accept a new effect to STARTED state without the need to explicitly stop and erase the previously uploaded effect beforehand */
+#define FFPL_HAS_NATIVE_GAIN BIT(15)  /* Device can adjust the gain by itself */
 
 enum ffpl_control_command {
        /* Force feedback state transitions */
@@ -22,7 +23,9 @@ enum ffpl_control_command {
        FFPL_EMP_TO_SRT, /* Upload and start effect */
        FFPL_SRT_TO_EMP, /* Stop and erase started effect */
        FFPL_OWR_TO_UPL, /* Overwrite an effect with a new one and set its state to UPLOADED */
-       FFPL_OWR_TO_SRT  /* Overwrite an effect with a new one and set its state to STARTED */
+       FFPL_OWR_TO_SRT, /* Overwrite an effect with a new one and set its state to STARTED */
+
+       FFPL_SET_GAIN    /* Set gain */
 };
 
 struct ffpl_effects {
@@ -37,7 +40,6 @@ union ffpl_control_data {
        u16 gain;
 };
 
-
 void ffpl_lvl_dir_to_x_y(const s32 level, const u16 direction, s32 *x, s32 *y);
 int ffpl_init_plugin(struct klgd_plugin **plugin, struct input_dev *dev, const size_t effect_count,
                     const unsigned long supported_effects,
index a125b7b90beea41ffb802a7a3e19a229742dccf4..5a0c9a918523a6630128f7ea6ce4dfe92f8465de 100644 (file)
@@ -14,7 +14,7 @@ enum ffpl_st_change {
 enum ffpl_state {
        FFPL_EMPTY,       /* There is no effect in the slot */
        FFPL_UPLOADED,    /* Effect in the slot is uploaded to device */
-       FFPL_STARTED,     /* Effect in the slot is started on device */
+       FFPL_STARTED      /* Effect in the slot is started on device */
 };
 
 /* What to do at the next timing trip point */
@@ -52,6 +52,7 @@ struct klgd_plugin_private {
        size_t effect_count;
        struct input_dev *dev;
        int (*control)(struct input_dev *dev, struct klgd_command_stream *s, const enum ffpl_control_command cmd, const union ffpl_control_data data);
+       u16 gain;
        /* Optional device capabilities */
        bool has_emp_to_srt;
        bool has_srt_to_emp;
@@ -59,5 +60,9 @@ struct klgd_plugin_private {
        bool erase_when_stopped;
        bool has_owr_to_upl;
        bool has_owr_to_srt;
-       u32 padding:26;
+       bool has_native_gain;
+       u32 padding_caps:25;
+       /* Device-wide state changes */
+       bool change_gain;
+       u32 padding_dw:31;
 };
index fc1c6c78f37d1a77c031eb8934cf74c84c1b8b5a..1b9012e06df988b8921a6934f68439ed22ff398d 100644 (file)
--- a/klgdff.c
+++ b/klgdff.c
@@ -12,6 +12,7 @@ static struct kobject *klgdff_obj;
 static struct input_dev *dev;
 static struct klgd_main klgd;
 static struct klgd_plugin *ff_plugin;
+static u16 gain;
 
 static int klgdff_erase(struct klgd_command_stream *s, const struct ff_effect *effect)
 {
@@ -69,6 +70,22 @@ static int klgdff_er_stop(struct klgd_command_stream *s, const struct ff_effect
        return klgd_append_cmd(s, c);
 }
 
+static int klgdff_set_gain(struct klgd_command_stream *s, const u16 _gain)
+{
+       char *text = kasprintf(GFP_KERNEL, "Setting gain to: %u", _gain);
+       size_t len = strlen(text);
+       struct klgd_command *c = klgd_alloc_cmd(len + 1);
+
+       if (!c)
+               return -ENOMEM;
+
+       gain = _gain;
+
+       memcpy(c->bytes, text, len);
+       kfree(text);
+       return klgd_append_cmd(s, c);
+}
+
 static int klgdff_start(struct klgd_command_stream *s, const struct ff_effect *effect, const int repeat)
 {
        char *text;
@@ -80,9 +97,10 @@ static int klgdff_start(struct klgd_command_stream *s, const struct ff_effect *e
        {
                s32 x;
                s32 y;
+               s16 level = effect->u.constant.level * gain / 0xFFFF;
 
-               ffpl_lvl_dir_to_x_y(effect->u.constant.level, effect->direction, &x, &y);
-               text = kasprintf(GFP_KERNEL, "Playing FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", effect->u.constant.level, effect->direction, x, y);
+               ffpl_lvl_dir_to_x_y(level, effect->direction, &x, &y);
+               text = kasprintf(GFP_KERNEL, "Playing FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", level, effect->direction, x, y);
                break;
        }
        default:
@@ -126,9 +144,10 @@ static int klgdff_update(struct klgd_command_stream *s, const struct ff_effect *
        {
                s32 x;
                s32 y;
+               s16 level = effect->u.constant.level * gain / 0xFFFF;
 
-               ffpl_lvl_dir_to_x_y(effect->u.constant.level, effect->direction, &x, &y);
-               text = kasprintf(GFP_KERNEL, "Updating FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", effect->u.constant.level, effect->direction, x, y);
+               ffpl_lvl_dir_to_x_y(level, effect->direction, &x, &y);
+               text = kasprintf(GFP_KERNEL, "Updating FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", level, effect->direction, x, y);
                break;
        }
        default:
@@ -172,9 +191,10 @@ static int klgdff_up_start(struct klgd_command_stream *s, const struct ff_effect
        {
                s32 x;
                s32 y;
+               s16 level = effect->u.constant.level * gain / 0xFFFF;
 
-               ffpl_lvl_dir_to_x_y(effect->u.constant.level, effect->direction, &x, &y);
-               text = kasprintf(GFP_KERNEL, "Uploading and starting FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", effect->u.constant.level, effect->direction, x, y);
+               ffpl_lvl_dir_to_x_y(level, effect->direction, &x, &y);
+               text = kasprintf(GFP_KERNEL, "Uploading and starting FF_CONSTANT, level: %d, dir: %u, X: %d, Y: %d", level, effect->direction, x, y);
                break;
        }
        default:
@@ -249,6 +269,8 @@ int klgdff_control(struct input_dev *dev, struct klgd_command_stream *s, const e
         case FFPL_OWR_TO_UPL:
                return klgdff_owr_upload(s, data.effects.cur, data.effects.old);
                break;
+       case FFPL_SET_GAIN:
+               return klgdff_set_gain(s, data.gain);
        default:
                printk(KERN_NOTICE "KLGDFF-TD - Unhandled command\n");
                break;
@@ -281,6 +303,7 @@ static int __init klgdff_init(void)
        if (!klgdff_obj)
                return -ENOMEM;
 
+
        ret = klgd_init(&klgd, NULL, klgdff_callback, 1);
        if (ret) {
                printk(KERN_ERR "KLGDFF-TD: Cannot initialize KLGD\n");
@@ -300,6 +323,7 @@ static int __init klgdff_init(void)
        dev->name = kasprintf(GFP_KERNEL, "KLGD-FF TestModule");
        dev->uniq = kasprintf(GFP_KERNEL, "KLGD-FF TestModule-X");
        dev->dev.parent = NULL;
+       gain = 0xFFFF;
 
        input_set_capability(dev, EV_ABS, ABS_X);
        input_set_capability(dev, EV_ABS, ABS_Y);