Skip to content

Commit

Permalink
hid_xpadneo, rumble: Optimize motor reprogramming
Browse files Browse the repository at this point in the history
Maybe-fixes: atar-axis#189
Signed-off-by: Kai Krakow <[email protected]>
  • Loading branch information
kakra committed Jun 8, 2020
1 parent abf398e commit e50ecab
Showing 1 changed file with 32 additions and 21 deletions.
53 changes: 32 additions & 21 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,48 +204,42 @@ static void xpadneo_ff_worker(struct work_struct *work)
struct ff_report *r = xdata->output_report_dmabuf;
int ret;

/* generate no report when magnitudes are still the same */
if (memcmp(&xdata->ff_shadow, &xdata->ff, sizeof(xdata->ff)) == 0)
return;
else
memcpy(&xdata->ff_shadow, &xdata->ff, sizeof(xdata->ff));

memset(r, 0, sizeof(*r));

r->report_id = XPADNEO_XB1S_FF_REPORT;

r->ff.enable = FF_RUMBLE_ALL;
if (unlikely(xdata->quirks & XPADNEO_QUIRK_NO_TRIGGER_RUMBLE))
r->ff.enable &= ~FF_RUMBLE_TRIGGERS;

/* if pulse is not supported, we do not have to care about explicitly
* stopping the effect, the kernel will do this for us as part of its
* ff-memless emulation
*/
if (likely((xdata->quirks & XPADNEO_QUIRK_NO_PULSE) == 0)) {
/*
* ff-memless has a time resolution of 50ms but we pulse the motors
* as long as possible
* ff-memless has a time resolution of 50ms but we pulse the
* motors as long as possible as we also optimize out
* repeated motor programming below
*/
r->ff.pulse_sustain_10ms = U8_MAX;
r->ff.loop_count = U8_MAX;
}

if (likely((xdata->quirks & XPADNEO_QUIRK_NO_TRIGGER_RUMBLE) == 0)) {
/* main motors */
r->ff.magnitude_strong = xdata->ff.magnitude_strong;
r->ff.magnitude_weak = xdata->ff.magnitude_weak;

if (unlikely(xdata->quirks & XPADNEO_QUIRK_NO_TRIGGER_RUMBLE)) {
/* do not send these bits if not supported */
r->ff.enable &= ~FF_RUMBLE_TRIGGERS;
} else {
/* trigger motors */
r->ff.magnitude_left = xdata->ff.magnitude_left;
r->ff.magnitude_right = xdata->ff.magnitude_right;
}

/* main motors */
r->ff.magnitude_strong = xdata->ff.magnitude_strong;
r->ff.magnitude_weak = xdata->ff.magnitude_weak;

/*
* if we cannot mask motors from the command, we need to explicitly
* set the strength to 0
*/
if (unlikely(xdata->quirks & XPADNEO_QUIRK_NO_MOTOR_MASK)) {
/*
* if we cannot mask motors from the command, we need to
* explicitly set the strength to 0
*/
if (likely((r->ff.enable & FF_RUMBLE_STRONG) == 0))
r->ff.magnitude_strong = 0;
if (likely((r->ff.enable & FF_RUMBLE_WEAK) == 0))
Expand All @@ -254,8 +248,25 @@ static void xpadneo_ff_worker(struct work_struct *work)
r->ff.magnitude_left = 0;
if (unlikely((r->ff.enable & FF_RUMBLE_RIGHT) == 0))
r->ff.magnitude_right = 0;
} else {
/* do not reprogram motors that have not changed */
if (xdata->ff_shadow.magnitude_strong == r->ff.magnitude_strong)
r->ff.enable &= ~FF_RUMBLE_STRONG;
if (xdata->ff_shadow.magnitude_weak == r->ff.magnitude_weak)
r->ff.enable &= ~FF_RUMBLE_WEAK;
if (xdata->ff_shadow.magnitude_left == r->ff.magnitude_left)
r->ff.enable &= ~FF_RUMBLE_LEFT;
if (xdata->ff_shadow.magnitude_right == r->ff.magnitude_right)
r->ff.enable &= ~FF_RUMBLE_RIGHT;

/* do not send a report if nothing changed */
if (r->ff.enable == FF_RUMBLE_NONE)
return;
}

/* shadow our current rumble values for the next cycle */
memcpy(&xdata->ff_shadow, &xdata->ff, sizeof(xdata->ff));

ret = hid_hw_output_report(hdev, (__u8 *) r, sizeof(*r));
if (ret < 0)
hid_warn(hdev, "failed to send FF report: %d\n", ret);
Expand Down

0 comments on commit e50ecab

Please sign in to comment.