Skip to content

Commit

Permalink
hid-xpadneo, rumble: Do not lose rumble strength while throttled
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
kakra committed Jun 23, 2021
1 parent abdc756 commit 5bfa6a6
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 5bfa6a6

Please sign in to comment.