]> Devoid-pointer.net GitWeb - KLGD_FF_plugin.git/commitdiff
Initial implementation of rumble effects combining
authorMichal Malý <madcatxster@devoid-pointer.net>
Sun, 20 Sep 2015 19:41:44 +0000 (21:41 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Sun, 20 Sep 2015 19:41:44 +0000 (21:41 +0200)
klgd_ff_plugin.c
klgd_ff_plugin.h
klgd_ff_plugin_p.h
klgdff.c

index 830257fb79060554499687816dbaab734ce551fd..313a712efb6a9659b5dfba046e96f3f86d0b0a07 100644 (file)
@@ -11,6 +11,47 @@ MODULE_DESCRIPTION("KLGD-FF Module");
 #define DIR_TO_DEGREES(dir) (360 - ((((dir > 0xc000) ? (u32)dir + 0x4000 - 0xffff : (u32)dir + 0x4000) * 360) / 0xffff))
 #define FRAC_16 15
 #define RECALC_DELTA_T_MSEC 20
+#define NEEDS_UPDATE_SET(etype, ffbit) \
+       do { \
+               switch (etype) { \
+               case FF_CONSTANT: \
+               case FF_RAMP: \
+                       needs_update_cf = true; \
+                       break; \
+               case FF_RUMBLE: \
+                       needs_update_rumble = true; \
+                       break; \
+               case FF_PERIODIC: \
+                       if (test_bit(FF_CONSTANT, ffbit)) \
+                               needs_update_cf = true; \
+                       else \
+                               needs_update_rumble = true; \
+                       break; \
+               default: \
+                       break; \
+               } \
+       } while (0);
+
+#define ACTIVE_EFFECTS_INC(etype, ffbit) \
+       do { \
+               switch (etype) { \
+               case FF_CONSTANT: \
+               case FF_RAMP: \
+                       active_effects_cf++; \
+                       break; \
+               case FF_RUMBLE: \
+                       active_effects_rumble++; \
+                       break; \
+               case FF_PERIODIC: \
+                       if (test_bit(FF_CONSTANT, ffbit)) \
+                               active_effects_cf++; \
+                       else \
+                               active_effects_rumble++; \
+                       break; \
+               default: \
+                       break; \
+               } \
+       } while (0);
 
 static int ffpl_handle_state_change(struct klgd_plugin_private *priv, struct klgd_command_stream *s, struct ffpl_effect *eff,
                                    const unsigned long now);
@@ -35,6 +76,8 @@ inline static bool ffpl_process_memless(const struct klgd_plugin_private *priv,
                return priv->memless_periodic;
        case FF_RAMP:
                return priv->memless_ramp;
+       case FF_RUMBLE:
+               return priv->memless_rumble;
        default:
                return false;
        }
@@ -328,10 +371,10 @@ static void ffpl_ramp_to_x_y(struct ffpl_effect *eff, s32 *x, s32 *y, const unsi
        ffpl_lvl_dir_to_x_y(new, ueff->direction, x, y);
 }
 
-static void ffpl_recalc_combined(struct klgd_plugin_private *priv, const unsigned long now)
+static void ffpl_recalc_combined_cf(struct klgd_plugin_private *priv, const unsigned long now, const bool handle_periodic)
 {
        size_t idx;
-       struct ff_effect *cb_latest = &priv->combined_effect.latest;
+       struct ff_effect *cb_latest = &priv->combined_effect_cf.latest;
        s32 x = 0;
        s32 y = 0;
 
@@ -349,6 +392,8 @@ static void ffpl_recalc_combined(struct klgd_plugin_private *priv, const unsigne
                        ffpl_constant_to_x_y(eff, &_x, &_y, now);
                        break;
                case FF_PERIODIC:
+                       if (!handle_periodic)
+                               break;
                        ffpl_periodic_to_x_y(eff, &_x, &_y, now);
                        break;
                case FF_RAMP:
@@ -370,6 +415,26 @@ static void ffpl_recalc_combined(struct klgd_plugin_private *priv, const unsigne
               cb_latest->direction);
 }
 
+static void ffpl_recalc_combined_rumble(struct klgd_plugin_private *priv, const unsigned long now, const bool handle_periodic)
+{
+       size_t idx;
+       struct ff_effect *cb_latest = &priv->combined_effect_rumble.latest;
+
+       for (idx = 0; idx < priv->effect_count; idx++) {
+               struct ffpl_effect *eff = &priv->effects[idx];
+               struct ff_effect *ueff = &eff->active;
+
+               switch (ueff->type) {
+               case FF_RUMBLE:
+                       break;
+               case FF_PERIODIC:
+                       if (!handle_periodic)
+                               break;
+                       break;
+               }
+       }
+}
+
 static int ffpl_erase_effect(struct klgd_plugin_private *priv, struct klgd_command_stream *s, struct ffpl_effect *eff)
 {
        if (eff->uploaded_to_device) {
@@ -698,8 +763,10 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
                                          const unsigned long now)
 {
        size_t idx;
-       bool needs_update = false;
-       size_t active_effects = 0;
+       bool needs_update_cf = false;
+       bool needs_update_rumble = false;
+       size_t active_effects_cf = 0;
+       size_t active_effects_rumble = 0;
 
        for (idx = 0; idx < priv->effect_count; idx++) {
                int ret;
@@ -730,7 +797,7 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
                        /* Combinable effect is being replaced by an uncombinable one */
                                printk(KERN_NOTICE "KLGDFF: Replacing combinable with uncombinable\n");
                                if (eff->state == FFPL_STARTED)
-                                       needs_update = true;
+                                       NEEDS_UPDATE_SET(eff->active.type, priv->dev->ffbit);
                                eff->state = FFPL_EMPTY;
                                eff->replace = false;
                                continue;
@@ -743,14 +810,14 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
                switch (eff->change) {
                case FFPL_DONT_TOUCH:
                        if (eff->state == FFPL_STARTED) {
-                               active_effects++;
+                               ACTIVE_EFFECTS_INC(eff->active.type, priv->dev->ffbit);
                                if (eff->recalculate) {
-                                       needs_update = true;
+                                       NEEDS_UPDATE_SET(eff->active.type, priv->dev->ffbit);
                                        eff->recalculate = false;
-                                       printk(KERN_NOTICE "KLGDFF: Recalculable combinable effect, total active effects %lu\n", active_effects);
+                                       printk(KERN_NOTICE "KLGDFF: Recalculable combinable effect, total active effects (CF/Rumble) %lu/%lu\n", active_effects_cf, active_effects_rumble);
                                }
                        } else
-                               printk(KERN_NOTICE "KLGDFF: Unchanged combinable effect, total active effects %lu\n", active_effects);
+                               printk(KERN_NOTICE "KLGDFF: Unchanged combinable effect, total active effects (CF/Rumble) %lu/%lu\n", active_effects_cf, active_effects_rumble);
                        break;
                case FFPL_TO_START:
                        eff->state = FFPL_STARTED;
@@ -760,13 +827,14 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
                                printk(KERN_NOTICE "KLGDFF: Updating a stopped combinable effect\n");
                                break;
                        }
-                       active_effects++;
-                       needs_update = true;
-                       printk(KERN_NOTICE "KLGDFF: %s combinable effect, total active effects %lu\n", eff->change == FFPL_TO_START ? "Started" : "Altered", active_effects);
+                       ACTIVE_EFFECTS_INC(eff->active.type, priv->dev->ffbit);
+                       NEEDS_UPDATE_SET(eff->active.type, priv->dev->ffbit);
+                       printk(KERN_NOTICE "KLGDFF: %s combinable effect, total active effects (CF/Rumble) %lu/%lu\n", eff->change == FFPL_TO_START ? "Started" : "Altered",
+                              active_effects_cf, active_effects_rumble);
                        break;
                case FFPL_TO_STOP:
                        if (eff->state == FFPL_STARTED)
-                               needs_update = true;
+                               NEEDS_UPDATE_SET(eff->active.type, priv->dev->ffbit);
                case FFPL_TO_UPLOAD:
                        eff->active = eff->latest;
                        eff->state = FFPL_UPLOADED;
@@ -774,9 +842,9 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
                        break;
                case FFPL_TO_ERASE:
                        if (eff->state == FFPL_STARTED)
-                               needs_update = true;
+                               NEEDS_UPDATE_SET(eff->active.type, priv->dev->ffbit);
                        eff->state = FFPL_EMPTY;
-                       printk(KERN_NOTICE "KLGDFF: Stopped combinable effect, total active effects %lu\n", active_effects);
+                       printk(KERN_NOTICE "KLGDFF: Stopped combinable effect, total active effects (CF/Rumble) %lu/%lu\n", active_effects_cf, active_effects_rumble);
                        break;
                default:
                        printk(KERN_WARNING "KLGDFF: Unknown effect change!\n");
@@ -787,21 +855,37 @@ static int ffpl_handle_combinable_effects(struct klgd_plugin_private *priv, stru
        }
 
        /* Combined effect needs recalculation */
-       if (needs_update) {
-               if (active_effects) {
-                       printk(KERN_NOTICE "KLGDFF: Combined effect needs an update, total effects active: %lu\n", active_effects);
-                       ffpl_recalc_combined(priv, now);
-                       if (priv->combined_effect.state == FFPL_STARTED)
-                               priv->combined_effect.change = FFPL_TO_UPDATE;
+       if (needs_update_cf) {
+               if (active_effects_cf) {
+                       printk(KERN_NOTICE "KLGDFF: Combined constant force effect needs an update, total effects active: %lu\n", active_effects_cf);
+                       ffpl_recalc_combined_cf(priv, now, test_bit(FF_CONSTANT, priv->dev->ffbit));
+                       if (priv->combined_effect_cf.state == FFPL_STARTED)
+                               priv->combined_effect_cf.change = FFPL_TO_UPDATE;
                        else
-                               priv->combined_effect.change = FFPL_TO_START;
-
-                       return 0;
+                               priv->combined_effect_cf.change = FFPL_TO_START;
+               } else {
+                       /* No combinable effects are active, remove the effect from device */
+                       if (priv->combined_effect_cf.state != FFPL_EMPTY) {
+                               printk(KERN_NOTICE "KLGDFF: No combinable constant force effects are active, erase the combined constant force effect from device\n");
+                               priv->combined_effect_cf.change = FFPL_TO_ERASE;
+                       }
                }
-               /* No combinable effects are active, remove the effect from device */
-               if (priv->combined_effect.state != FFPL_EMPTY) {
-                       printk(KERN_NOTICE "KLGDFF: No combinable effects are active, erase the combined effect from device\n");
-                       priv->combined_effect.change = FFPL_TO_ERASE;
+       }
+
+       if (needs_update_rumble) {
+               if (active_effects_rumble) {
+                       printk(KERN_NOTICE "KLGDFF: Combined rumble effect needs an update, total effects active: %lu\n", active_effects_rumble);
+                       ffpl_recalc_combined_rumble(priv, now, test_bit(FF_CONSTANT, priv->dev->ffbit));
+                       if (priv->combined_effect_rumble.state == FFPL_STARTED)
+                               priv->combined_effect_rumble.change = FFPL_TO_UPDATE;
+                       else
+                               priv->combined_effect_rumble.change = FFPL_TO_START;
+               } else {
+                       /* No combinable effects are active, remove the effect from device */
+                       if (priv->combined_effect_rumble.state != FFPL_EMPTY) {
+                               printk(KERN_NOTICE "KLGDFF: No combinable rumble effects are active, erase the combined effect from device\n");
+                               priv->combined_effect_rumble.change = FFPL_TO_ERASE;
+                       }
                }
        }
 
@@ -1002,9 +1086,9 @@ static int ffpl_get_commands(struct klgd_plugin *self, struct klgd_command_strea
        }
 
        /* Handle combined effect here */
-       ret = ffpl_handle_state_change(priv, *s, &priv->combined_effect, now);
+       ret = ffpl_handle_state_change(priv, *s, &priv->combined_effect_cf, now);
        if (ret) {
-               printk(KERN_WARNING "KLGDFF: Cannot get command stream for combined effect\n");
+               printk(KERN_WARNING "KLGDFF: Cannot get command stream for combined constant force effect\n");
                goto out;
        }
 
@@ -1383,6 +1467,8 @@ int ffpl_init_plugin(struct klgd_plugin **plugin, struct input_dev *dev, const s
                priv->memless_periodic = true;
        if (FFPL_MEMLESS_RAMP & flags)
                priv->memless_ramp = true;
+       if (FFPL_MEMLESS_RUMBLE & flags)
+               priv->memless_rumble = true;
        if (FFPL_TIMING_CONDITION & flags)
                priv->timing_condition = true;
 
index e7c7e4c1f707879e8b8fde2f27f2dd35b47ff0d8..f110e8be83927ef0460513b7b97a07376e9d73b2 100644 (file)
                                            Device must support FF_CONSTANT for this to work. */
 #define FFPL_MEMLESS_RAMP BIT(8)        /* Device cannot process FF_RAMP by itself and requires KLGD-FF to calculate the overall force.
                                            Device must support FF_CONSTANT for this to work. */
-#define FFPL_TIMING_CONDITION BIT(9)    /* Let the plugin take care of starting and stopping of condition effects */
+#define FFPL_MEMLESS_RUMBLE BIT(9)      /* Device cannot process FF_RUMBLE by itself and requires KLGD-FF to calculate the overall force.
+                                           Device must support FF_RUMBLE for this to work. */
+
+#define FFPL_TIMING_CONDITION BIT(10)   /* Let the plugin take care of starting and stopping of condition effects */
 
 #define FFPL_HAS_NATIVE_GAIN BIT(15)  /* Device can adjust the gain by itself */
 #define FFPL_HAS_AUTOCENTER BIT(16) /* Device supports autocentering */
index 60dac459fda6f24287e68e6fc612e6716e7b896e..a064497029c3cd24be484ac9eaa349d85aefb888 100644 (file)
@@ -48,7 +48,8 @@ struct ffpl_effect {
 
 struct klgd_plugin_private {
        struct ffpl_effect *effects;
-       struct ffpl_effect combined_effect;
+       struct ffpl_effect combined_effect_cf;
+       struct ffpl_effect combined_effect_rumble;
        unsigned long supported_effects;
        size_t effect_count;
        struct input_dev *dev;
@@ -68,8 +69,9 @@ struct klgd_plugin_private {
        bool memless_constant;
        bool memless_periodic;
        bool memless_ramp;
+       bool memless_rumble;
        bool timing_condition;
-       u32 padding_caps:20;
+       u32 padding_caps:19;
        /* Device-wide state changes */
        bool change_gain;
        bool change_autocenter;
index 83fe1606a367c1fc7bf1279aadacb8f9d1596833..f282dcddd805f2d2bb070e6c4aa687d4d19b0599 100644 (file)
--- a/klgdff.c
+++ b/klgdff.c
@@ -356,7 +356,8 @@ static int __init klgdff_init(void)
        input_set_abs_params(dev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
 
        ret = ffpl_init_plugin(&ff_plugin, dev, EFFECT_COUNT, ffbits,
-                              FFPL_HAS_EMP_TO_SRT | FFPL_REPLACE_STARTED | FFPL_HAS_AUTOCENTER | FFPL_MEMLESS_RAMP | FFPL_TIMING_CONDITION,
+                              FFPL_HAS_EMP_TO_SRT | FFPL_REPLACE_STARTED | FFPL_HAS_AUTOCENTER |
+                              FFPL_MEMLESS_CONSTANT | FFPL_MEMLESS_RUMBLE | FFPL_TIMING_CONDITION,
                               klgdff_control, &test_user);
        if (ret) {
                printk(KERN_ERR "KLGDFF-TD: Cannot init plugin\n");