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

[Bug] Fix mouse-key spamming empty reports #21663

Merged
merged 1 commit into from
Aug 2, 2023
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
Fix mouse-key spamming empty reports
Problem:

`mousekey_task` spams empty hid reports with when a mouse key is
pressed, causing resource exhaustion in the USB mouse endpoint.

Cause:

The check whether or not to send a new mouse report would always
evaluate to true if a mouse key is pressed:

1. `mouse_report` has non-zero fields and `tmpmr` is a copy of this
   fields.
2. `mouse_report` is set to zero, `tmpmr` has now non-zero fields.
3. `has_mouse_report_changed` compares the two and evaluates to true
4. a mouse report is sent.

Fix:

The check condition of `has_mouse_report_changed` will evaluate any
empty record as unchanged, as mouse report data is relative and doesn't
need to return to zero. An empty report will still be send by
`register_mouse` on release of all mouse buttons.
  • Loading branch information
KarlK90 committed Aug 2, 2023
commit 850d3b6376e83b4eeb61062e93c62dbf45a0bd71
12 changes: 10 additions & 2 deletions tmk_core/protocol/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,21 @@ void clear_keys_from_report(report_keyboard_t* keyboard_report) {

#ifdef MOUSE_ENABLE
/**
* @brief Compares 2 mouse reports for difference and returns result
* @brief Compares 2 mouse reports for difference and returns result. Empty
* reports always evaluate as unchanged.
*
* @param[in] new_report report_mouse_t
* @param[in] old_report report_mouse_t
* @return bool result
*/
__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report) {
return memcmp(new_report, old_report, sizeof(report_mouse_t));
// memcmp doesn't work here because of the `report_id` field when using
// shared mouse endpoint
bool changed = ((new_report->buttons != old_report->buttons) ||
# ifdef MOUSE_EXTENDED_REPORT
(new_report->boot_x != 0 && new_report->boot_x != old_report->boot_x) || (new_report->boot_y != 0 && new_report->boot_y != old_report->boot_y) ||
# endif
(new_report->x != 0 && new_report->x != old_report->x) || (new_report->y != 0 && new_report->y != old_report->y) || (new_report->h != 0 && new_report->h != old_report->h) || (new_report->v != 0 && new_report->v != old_report->v));
return changed;
}
#endif