summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreynsai <47629346+eynsai@users.noreply.github.com>2025-04-22 18:04:31 -0400
committerGitHub <noreply@github.com>2025-04-23 00:04:31 +0200
commit7a2cd0fa962eb5e6e18ce8b0213a7171bc823c1f (patch)
treed7c62b67ba4d9402b822768d7013803d99cb9484
parent83818d1d6f7d1f590946756ad552e407bf9a2e1f (diff)
High resolution scrolling (without feature report parsing) (#24423)
* hires scrolling without feature report parsing * fix valid range for exponent * fix incorrect minimum exponent value documentation
-rw-r--r--docs/features/pointing_device.md26
-rw-r--r--quantum/pointing_device/pointing_device.c19
-rw-r--r--quantum/pointing_device/pointing_device.h4
-rw-r--r--tmk_core/protocol/usb_descriptor.c24
-rw-r--r--tmk_core/protocol/usb_descriptor_common.h20
-rw-r--r--tmk_core/protocol/vusb/vusb.c28
6 files changed, 119 insertions, 2 deletions
diff --git a/docs/features/pointing_device.md b/docs/features/pointing_device.md
index 0ecf82c8df..a139df9dc4 100644
--- a/docs/features/pointing_device.md
+++ b/docs/features/pointing_device.md
@@ -419,6 +419,32 @@ The `POINTING_DEVICE_CS_PIN`, `POINTING_DEVICE_SDIO_PIN`, and `POINTING_DEVICE_S
419Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE`. e.g. PMW3360 can use Lift_Stat from Motion register. Note that `POINTING_DEVICE_MOTION_PIN` cannot be used with this feature; continuous polling of `get_report()` is needed to generate glide reports. 419Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE`. e.g. PMW3360 can use Lift_Stat from Motion register. Note that `POINTING_DEVICE_MOTION_PIN` cannot be used with this feature; continuous polling of `get_report()` is needed to generate glide reports.
420::: 420:::
421 421
422## High Resolution Scrolling
423
424| Setting | Description | Default |
425| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- |
426| `POINTING_DEVICE_HIRES_SCROLL_ENABLE` | (Optional) Enables high resolution scrolling. | _not defined_ |
427| `POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER`| (Optional) Resolution mutiplier value used by high resolution scrolling. Must be between 1 and 127, inclusive. | `120` |
428| `POINTING_DEVICE_HIRES_SCROLL_EXPONENT` | (Optional) Resolution exponent value used by high resolution scrolling. Must be between 0 and 127, inclusive. | `0` |
429
430The `POINTING_DEVICE_HIRES_SCROLL_ENABLE` setting enables smooth and continuous scrolling when using trackballs or high-end encoders as mouse wheels (as opposed to the typical stepped behavior of most mouse wheels).
431This works by adding a resolution multiplier to the HID descriptor for mouse wheel reports, causing the host computer to interpret each wheel tick sent by the keyboard as a fraction of a normal wheel tick.
432The resolution multiplier is set to `1 / (POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER * (10 ^ POINTING_DEVICE_HIRES_SCROLL_EXPONENT))`, which is `1 / 120` by default.
433If even smoother scrolling than provided by this default value is desired, first try using `#define POINTING_DEVICE_HIRES_SCROLL_EXPONENT 1` which will result in a multiplier of `1 / 1200`.
434
435The function `pointing_device_get_hires_scroll_resolution()` can be called to get the pre-computed resolution multiplier value as a `uint16_t`.
436
437::: warning
438High resolution scrolling usually results in larger and/or more frequent mouse reports. This can result in overflow errors and overloading of the host computer's input buffer.
439To deal with these issues, define `WHEEL_EXTENDED_REPORT` and throttle the rate at which mouse reports are sent.
440:::
441
442::: warning
443Many programs, especially those that implement their own smoothing for scrolling, don't work well when they receive simultaneous vertical and horizontal wheel inputs (e.g. from high resolution drag-scroll using a trackball).
444These programs typically implement their smoothing in a way that assumes the user will only scroll in one axis at a time, resulting in slow or jittery motion when trying to scroll at an angle.
445This can be addressed by snapping scrolling to one axis at a time.
446:::
447
422## Split Keyboard Configuration 448## Split Keyboard Configuration
423 449
424The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](split_keyboard#data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device. 450The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](split_keyboard#data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device.
diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c
index e26416f968..5ee65c9c61 100644
--- a/quantum/pointing_device/pointing_device.c
+++ b/quantum/pointing_device/pointing_device.c
@@ -25,6 +25,10 @@
25# include "mousekey.h" 25# include "mousekey.h"
26#endif 26#endif
27 27
28#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
29# include "usb_descriptor_common.h"
30#endif
31
28#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 32#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
29# error More than one rotation selected. This is not supported. 33# error More than one rotation selected. This is not supported.
30#endif 34#endif
@@ -78,6 +82,9 @@ uint16_t pointing_device_get_shared_cpi(void) {
78 82
79static report_mouse_t local_mouse_report = {}; 83static report_mouse_t local_mouse_report = {};
80static bool pointing_device_force_send = false; 84static bool pointing_device_force_send = false;
85#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
86static uint16_t hires_scroll_resolution;
87#endif
81 88
82#define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver 89#define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver
83#define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name) 90#define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name)
@@ -176,6 +183,12 @@ __attribute__((weak)) void pointing_device_init(void) {
176# endif 183# endif
177#endif 184#endif
178 } 185 }
186#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
187 hires_scroll_resolution = POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER;
188 for (int i = 0; i < POINTING_DEVICE_HIRES_SCROLL_EXPONENT; i++) {
189 hires_scroll_resolution *= 10;
190 }
191#endif
179 192
180 pointing_device_init_kb(); 193 pointing_device_init_kb();
181 pointing_device_init_user(); 194 pointing_device_init_user();
@@ -523,3 +536,9 @@ __attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, boo
523 pointing_device_send(); 536 pointing_device_send();
524 } 537 }
525} 538}
539
540#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
541uint16_t pointing_device_get_hires_scroll_resolution(void) {
542 return hires_scroll_resolution;
543}
544#endif \ No newline at end of file
diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h
index 7bc059e594..d8b583c87e 100644
--- a/quantum/pointing_device/pointing_device.h
+++ b/quantum/pointing_device/pointing_device.h
@@ -122,6 +122,10 @@ uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, poi
122report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report); 122report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
123void pointing_device_keycode_handler(uint16_t keycode, bool pressed); 123void pointing_device_keycode_handler(uint16_t keycode, bool pressed);
124 124
125#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
126uint16_t pointing_device_get_hires_scroll_resolution(void);
127#endif
128
125#if defined(SPLIT_POINTING_ENABLE) 129#if defined(SPLIT_POINTING_ENABLE)
126void pointing_device_set_shared_report(report_mouse_t report); 130void pointing_device_set_shared_report(report_mouse_t report);
127uint16_t pointing_device_get_shared_cpi(void); 131uint16_t pointing_device_get_shared_cpi(void);
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index c7fb660b65..ceab9eef9a 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -165,6 +165,24 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
165# endif 165# endif
166 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), 166 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
167 167
168# ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
169 HID_RI_COLLECTION(8, 0x02),
170 // Feature report and padding (1 byte)
171 HID_RI_USAGE(8, 0x48), // Resolution Multiplier
172 HID_RI_REPORT_COUNT(8, 0x01),
173 HID_RI_REPORT_SIZE(8, 0x02),
174 HID_RI_LOGICAL_MINIMUM(8, 0x00),
175 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
176 HID_RI_PHYSICAL_MINIMUM(8, 1),
177 HID_RI_PHYSICAL_MAXIMUM(8, POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER),
178 HID_RI_UNIT_EXPONENT(8, POINTING_DEVICE_HIRES_SCROLL_EXPONENT),
179 HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
180 HID_RI_PHYSICAL_MINIMUM(8, 0x00),
181 HID_RI_PHYSICAL_MAXIMUM(8, 0x00),
182 HID_RI_REPORT_SIZE(8, 0x06),
183 HID_RI_FEATURE(8, HID_IOF_CONSTANT),
184# endif
185
168 // Vertical wheel (1 or 2 bytes) 186 // Vertical wheel (1 or 2 bytes)
169 HID_RI_USAGE(8, 0x38), // Wheel 187 HID_RI_USAGE(8, 0x38), // Wheel
170# ifndef WHEEL_EXTENDED_REPORT 188# ifndef WHEEL_EXTENDED_REPORT
@@ -179,6 +197,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
179 HID_RI_REPORT_SIZE(8, 0x10), 197 HID_RI_REPORT_SIZE(8, 0x10),
180# endif 198# endif
181 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), 199 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
200
182 // Horizontal wheel (1 or 2 bytes) 201 // Horizontal wheel (1 or 2 bytes)
183 HID_RI_USAGE_PAGE(8, 0x0C),// Consumer 202 HID_RI_USAGE_PAGE(8, 0x0C),// Consumer
184 HID_RI_USAGE(16, 0x0238), // AC Pan 203 HID_RI_USAGE(16, 0x0238), // AC Pan
@@ -194,6 +213,11 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
194 HID_RI_REPORT_SIZE(8, 0x10), 213 HID_RI_REPORT_SIZE(8, 0x10),
195# endif 214# endif
196 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), 215 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
216
217# ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
218 HID_RI_END_COLLECTION(0),
219# endif
220
197 HID_RI_END_COLLECTION(0), 221 HID_RI_END_COLLECTION(0),
198 HID_RI_END_COLLECTION(0), 222 HID_RI_END_COLLECTION(0),
199# ifndef MOUSE_SHARED_EP 223# ifndef MOUSE_SHARED_EP
diff --git a/tmk_core/protocol/usb_descriptor_common.h b/tmk_core/protocol/usb_descriptor_common.h
index 909c230a99..f782d83fbc 100644
--- a/tmk_core/protocol/usb_descriptor_common.h
+++ b/tmk_core/protocol/usb_descriptor_common.h
@@ -32,3 +32,23 @@
32#ifndef RAW_USAGE_ID 32#ifndef RAW_USAGE_ID
33# define RAW_USAGE_ID 0x61 33# define RAW_USAGE_ID 0x61
34#endif 34#endif
35
36/////////////////////
37// Hires Scroll Defaults
38
39#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
40# ifdef POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER
41# if POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER > 127 || POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER < 1
42# error "POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER must be between 1 and 127, inclusive!"
43# endif
44# else
45# define POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER 120
46# endif
47# ifdef POINTING_DEVICE_HIRES_SCROLL_EXPONENT
48# if POINTING_DEVICE_HIRES_SCROLL_EXPONENT > 127 || POINTING_DEVICE_HIRES_SCROLL_EXPONENT < 0
49# error "POINTING_DEVICE_HIRES_SCROLL_EXPONENT must be between 0 and 127, inclusive!"
50# endif
51# else
52# define POINTING_DEVICE_HIRES_SCROLL_EXPONENT 0
53# endif
54#endif \ No newline at end of file
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index fdbfcc17dc..56cf82e5a6 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -520,6 +520,24 @@ const PROGMEM uchar shared_hid_report[] = {
520# endif 520# endif
521 0x81, 0x06, // Input (Data, Variable, Relative) 521 0x81, 0x06, // Input (Data, Variable, Relative)
522 522
523# ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
524 // Feature report and padding (1 byte)
525 0xA1, 0x02, // Collection (Logical)
526 0x09, 0x48, // Usage (Resolution Multiplier)
527 0x95, 0x01, // Report Count (1)
528 0x75, 0x02, // Report Size (2)
529 0x15, 0x00, // Logical Minimum (0)
530 0x25, 0x01, // Logical Maximum (1)
531 0x35, 0x01, // Physical Minimum (1)
532 0x45, POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER, // Physical Maximum (POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER)
533 0x55, POINTING_DEVICE_HIRES_SCROLL_EXPONENT, // Unit Exponent (POINTING_DEVICE_HIRES_SCROLL_EXPONENT)
534 0xB1, 0x02, // Feature (Data, Variable, Absolute)
535 0x35, 0x00, // Physical Minimum (0)
536 0x45, 0x00, // Physical Maximum (0)
537 0x75, 0x06, // Report Size (6)
538 0xB1, 0x03, // Feature (Constant)
539# endif
540
523 // Vertical wheel (1 or 2 bytes) 541 // Vertical wheel (1 or 2 bytes)
524 0x09, 0x38, // Usage (Wheel) 542 0x09, 0x38, // Usage (Wheel)
525# ifndef WHEEL_EXTENDED_REPORT 543# ifndef WHEEL_EXTENDED_REPORT
@@ -534,6 +552,7 @@ const PROGMEM uchar shared_hid_report[] = {
534 0x75, 0x10, // Report Size (16) 552 0x75, 0x10, // Report Size (16)
535# endif 553# endif
536 0x81, 0x06, // Input (Data, Variable, Relative) 554 0x81, 0x06, // Input (Data, Variable, Relative)
555
537 // Horizontal wheel (1 or 2 bytes) 556 // Horizontal wheel (1 or 2 bytes)
538 0x05, 0x0C, // Usage Page (Consumer) 557 0x05, 0x0C, // Usage Page (Consumer)
539 0x0A, 0x38, 0x02, // Usage (AC Pan) 558 0x0A, 0x38, 0x02, // Usage (AC Pan)
@@ -549,8 +568,13 @@ const PROGMEM uchar shared_hid_report[] = {
549 0x75, 0x10, // Report Size (16) 568 0x75, 0x10, // Report Size (16)
550# endif 569# endif
551 0x81, 0x06, // Input (Data, Variable, Relative) 570 0x81, 0x06, // Input (Data, Variable, Relative)
552 0xC0, // End Collection 571
553 0xC0, // End Collection 572# ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
573 0xC0, // End Collection
574# endif
575
576 0xC0, // End Collection
577 0xC0, // End Collection
554#endif 578#endif
555 579
556#ifdef EXTRAKEY_ENABLE 580#ifdef EXTRAKEY_ENABLE