From 5bfa6a6b54dff57ef1aeec541fac021990d51dca 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. 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 99a294c0..7e55b9ef 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) {