summary refs log tree commit diff
path: root/tmk_core
diff options
context:
space:
mode:
authorStefan Kerkmann <karlk90@pm.me>2023-08-02 13:47:25 +0200
committerGitHub <noreply@github.com>2023-08-02 13:47:25 +0200
commitb2d068d1aa95265f16670cbf5a68da745602fc12 (patch)
tree650c658f69a6bffd62f12358360e3306804820dd /tmk_core
parent7fbc4153e8e27dd8c6456eef6e5ab5b01ed83ab9 (diff)
Fix mouse-key spamming empty reports (#21663)
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.
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/protocol/report.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c
index 5755098c60..1ba3be4604 100644
--- a/tmk_core/protocol/report.c
+++ b/tmk_core/protocol/report.c
@@ -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