diff options
author | Jiri Kosina <jkosina@suse.cz> | 2018-10-23 13:35:22 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2018-10-23 13:35:22 +0200 |
commit | 276e722761a1c7903fbfb065420fd1850b00f1dd (patch) | |
tree | 05cb4c39139da6d9132bab9e6b1c2ad7bc47394a /drivers/hid/hid-input.c | |
parent | 4e7be68e8d0f7bb3c030cdfa442d298457197751 (diff) | |
parent | d9ca1c990a7ffee7e68ab8d64efacd6c73103203 (diff) | |
download | linux-stable-276e722761a1c7903fbfb065420fd1850b00f1dd.tar.gz linux-stable-276e722761a1c7903fbfb065420fd1850b00f1dd.tar.bz2 linux-stable-276e722761a1c7903fbfb065420fd1850b00f1dd.zip |
Merge branch 'for-4.20/logitech-highres' into for-linus
High-resolution support for hid-logitech
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r-- | drivers/hid/hid-input.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index ad823a01bd65..567c3bf64515 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1838,3 +1838,48 @@ void hidinput_disconnect(struct hid_device *hid) } EXPORT_SYMBOL_GPL(hidinput_disconnect); +/** + * hid_scroll_counter_handle_scroll() - Send high- and low-resolution scroll + * events given a high-resolution wheel + * movement. + * @counter: a hid_scroll_counter struct describing the wheel. + * @hi_res_value: the movement of the wheel, in the mouse's high-resolution + * units. + * + * Given a high-resolution movement, this function converts the movement into + * microns and emits high-resolution scroll events for the input device. It also + * uses the multiplier from &struct hid_scroll_counter to emit low-resolution + * scroll events when appropriate for backwards-compatibility with userspace + * input libraries. + */ +void hid_scroll_counter_handle_scroll(struct hid_scroll_counter *counter, + int hi_res_value) +{ + int low_res_scroll_amount; + /* Some wheels will rest 7/8ths of a notch from the previous notch + * after slow movement, so we want the threshold for low-res events to + * be in the middle of the notches (e.g. after 4/8ths) as opposed to on + * the notches themselves (8/8ths). + */ + int threshold = counter->resolution_multiplier / 2; + + input_report_rel(counter->dev, REL_WHEEL_HI_RES, + hi_res_value * counter->microns_per_hi_res_unit); + + counter->remainder += hi_res_value; + if (abs(counter->remainder) >= threshold) { + /* Add (or subtract) 1 because we want to trigger when the wheel + * is half-way to the next notch (i.e. scroll 1 notch after a + * 1/2 notch movement, 2 notches after a 1 1/2 notch movement, + * etc.). + */ + low_res_scroll_amount = + counter->remainder / counter->resolution_multiplier + + (hi_res_value > 0 ? 1 : -1); + input_report_rel(counter->dev, REL_WHEEL, + low_res_scroll_amount); + counter->remainder -= + low_res_scroll_amount * counter->resolution_multiplier; + } +} +EXPORT_SYMBOL_GPL(hid_scroll_counter_handle_scroll); |