From beeab26ab4126916ac888f1bbec52042054a8b14 Mon Sep 17 00:00:00 2001 From: Kai Krakow Date: Sun, 11 Oct 2020 17:55:47 +0200 Subject: [PATCH] hid-xpadneo, rumble: Do not lose rumble strength while throttled While the rumble thread is throttled, we may actually miss the peak rumble strength resulting in an experience of rumbles with varying strength when these are repeatedly sent by a game. To work around this, we now accumulate the maximum strength set during the throttle interval, then reset the accumulator when a rumble has been sent to the controller. Maybe-fixes: https://github.com/atar-axis/xpadneo/issues/290 Signed-off-by: Kai Krakow --- hid-xpadneo/src/hid-xpadneo.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/hid-xpadneo/src/hid-xpadneo.c b/hid-xpadneo/src/hid-xpadneo.c index e7a8114a..3734059b 100644 --- a/hid-xpadneo/src/hid-xpadneo.c +++ b/hid-xpadneo/src/hid-xpadneo.c @@ -242,6 +242,12 @@ static void xpadneo_ff_worker(struct work_struct *work) /* shadow our current rumble values for the next cycle */ memcpy(&xdata->ff_shadow, &xdata->ff, sizeof(xdata->ff)); + /* clear the magnitudes to properly accumulate the maximum values */ + xdata->ff.magnitude_left = 0; + xdata->ff.magnitude_right = 0; + xdata->ff.magnitude_weak = 0; + xdata->ff.magnitude_strong = 0; + /* * throttle next command submission, the firmware doesn't like us to * send rumble data any faster @@ -259,6 +265,7 @@ static void xpadneo_ff_worker(struct work_struct *work) hid_warn(hdev, "failed to send FF report: %d\n", ret); } +#define update_magnitude(m, v) m = (v) > 0 ? max(m, v) : 0 static int xpadneo_ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { enum { @@ -369,12 +376,16 @@ static int xpadneo_ff_play(struct input_dev *dev, void *data, struct ff_effect * spin_lock_irqsave(&xdata->ff_lock, flags); /* calculate the physical magnitudes, scale from 16 bit to 0..100 */ - xdata->ff.magnitude_strong = (u8)((strong * fraction_MAIN + S16_MAX) / U16_MAX); - xdata->ff.magnitude_weak = (u8)((weak * fraction_MAIN + S16_MAX) / U16_MAX); + update_magnitude(xdata->ff.magnitude_strong, + (u8)((strong * fraction_MAIN + S16_MAX) / U16_MAX)); + update_magnitude(xdata->ff.magnitude_weak, + (u8)((weak * fraction_MAIN + S16_MAX) / U16_MAX)); /* calculate the physical magnitudes, scale from 16 bit to 0..100 */ - xdata->ff.magnitude_left = (u8)((max_main * fraction_TL + S16_MAX) / U16_MAX); - xdata->ff.magnitude_right = (u8)((max_main * fraction_TR + S16_MAX) / U16_MAX); + update_magnitude(xdata->ff.magnitude_left, + (u8)((max_main * fraction_TL + S16_MAX) / U16_MAX)); + update_magnitude(xdata->ff.magnitude_right, + (u8)((max_main * fraction_TR + S16_MAX) / U16_MAX)); /* synchronize: is our worker still scheduled? */ if (xdata->ff_scheduled) {