*y = (level * fixp_sin16(degrees)) >> FRAC_16;
}
-static bool ffpl_process_memless(const struct klgd_plugin_private *priv, const struct ff_effect *eff)
+inline static bool ffpl_process_memless(const struct klgd_plugin_private *priv, const struct ff_effect *eff)
{
switch (eff->type) {
case FF_CONSTANT:
}
}
+inline static bool ffpl_handle_timing(const struct klgd_plugin_private *priv, const struct ff_effect *eff)
+{
+ if (priv->timing_condition) {
+ switch (eff->type) {
+ case FF_DAMPER:
+ case FF_FRICTION:
+ case FF_INERTIA:
+ case FF_SPRING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ return ffpl_process_memless(priv, eff);
+}
+
static const struct ff_envelope * ffpl_get_envelope(const struct ff_effect *ueff)
{
switch (ueff->type) {
eff->repeat = value;
if (value > 0) {
- if (ffpl_process_memless(priv, &eff->latest))
+ if (ffpl_handle_timing(priv, &eff->latest))
ffpl_calculate_trip_times(eff, now);
else
eff->start_at = now; /* Start the effect right away and let the device deal with the timing */
const struct ff_envelope *env = ffpl_get_envelope(ueff);
bool ticks = ueff->type == FF_PERIODIC || ueff->type == FF_RAMP;
+ if (time_before(now, start_at)) {
+ printk(KERN_NOTICE "KLGDFF: Effect has not started yet\n");
+ return false;
+ }
+
/* Only effects handled by memless mode can be periodically reprocessed */
if (!ffpl_process_memless(priv, ueff)) {
printk(KERN_NOTICE "KLGDFF: Effect not combinable, won't recalculate\n");
eff->trigger = FFPL_TRIG_RECALC;
break;
}
- if (eff->latest.replay.length && ffpl_process_memless(priv, &eff->latest))
+ if (eff->latest.replay.length && ffpl_handle_timing(priv, &eff->latest))
eff->trigger = FFPL_TRIG_STOP;
else
eff->trigger = FFPL_TRIG_NONE;
eff->trigger = FFPL_TRIG_NONE;
break;
case FFPL_TRIG_STOP:
- if (eff->repeat > 0 && ffpl_process_memless(priv, &eff->active)) {
+ if (eff->repeat > 0 && ffpl_handle_timing(priv, &eff->active)) {
eff->trigger = FFPL_TRIG_RESTART;
break;
}
priv->memless_periodic = true;
if (FFPL_MEMLESS_RAMP & flags)
priv->memless_ramp = true;
+ if (FFPL_TIMING_CONDITION & flags)
+ priv->timing_condition = true;
if (FFPL_HAS_NATIVE_GAIN & flags) {
priv->has_native_gain = true;
#define FFPL_MEMLESS_CONSTANT BIT(6) /* Device cannot process FF_CONSTANT by itself and requires KLGD-FF to calculate overall force.
Device must support FF_CONSTANT for this to work. */
-#define FFPL_MEMLESS_PERIODIC BIT(7) /* Device cannot process FF_PERIODIC by itself and requires KLGD-FF to calculate the overall force.
- 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_MEMLESS_PERIODIC BIT(7) /* Device cannot process FF_PERIODIC by itself and requires KLGD-FF to calculate the overall force.
+ 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_HAS_NATIVE_GAIN BIT(15) /* Device can adjust the gain by itself */
#define FFPL_HAS_AUTOCENTER BIT(16) /* Device supports autocentering */
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_HAS_EMP_TO_SRT | FFPL_REPLACE_STARTED | FFPL_HAS_AUTOCENTER | FFPL_MEMLESS_RAMP | FFPL_TIMING_CONDITION,
klgdff_control, &test_user);
if (ret) {
printk(KERN_ERR "KLGDFF-TD: Cannot init plugin\n");