Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hid_xpadneo, rumble: Optimize motor reprogramming #202

Merged
merged 1 commit into from
Jun 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,34 +204,28 @@ 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)) {
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;
Expand All @@ -241,19 +235,26 @@ static void xpadneo_ff_worker(struct work_struct *work)
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
*/
/* do not reprogram motors that have not changed */
if (unlikely(xdata->ff_shadow.magnitude_strong == r->ff.magnitude_strong))
r->ff.enable &= ~FF_RUMBLE_STRONG;
if (unlikely(xdata->ff_shadow.magnitude_weak == r->ff.magnitude_weak))
r->ff.enable &= ~FF_RUMBLE_WEAK;
if (likely(xdata->ff_shadow.magnitude_left == r->ff.magnitude_left))
r->ff.enable &= ~FF_RUMBLE_LEFT;
if (likely(xdata->ff_shadow.magnitude_right == r->ff.magnitude_right))
r->ff.enable &= ~FF_RUMBLE_RIGHT;

/* do not send a report if nothing changed */
if (unlikely(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));

/* do not send these bits if not supported */
if (unlikely(xdata->quirks & XPADNEO_QUIRK_NO_MOTOR_MASK)) {
if (likely((r->ff.enable & FF_RUMBLE_STRONG) == 0))
r->ff.magnitude_strong = 0;
if (likely((r->ff.enable & FF_RUMBLE_WEAK) == 0))
r->ff.magnitude_weak = 0;
if (unlikely((r->ff.enable & FF_RUMBLE_LEFT) == 0))
r->ff.magnitude_left = 0;
if (unlikely((r->ff.enable & FF_RUMBLE_RIGHT) == 0))
r->ff.magnitude_right = 0;
r->ff.enable = 0;
}

ret = hid_hw_output_report(hdev, (__u8 *) r, sizeof(*r));
Expand Down