Message ID | 20220914132146.6435-1-hadess@hadess.net |
---|---|
State | Accepted |
Commit | 908d325e1665b2781085580070554cbbe5fc3c89 |
Headers | show |
Series | [v1] HID: logitech-hidpp: Detect hi-res scrolling support | expand |
On Wed, 2022-09-14 at 15:21 +0200, Bastien Nocera wrote: > Rather than relying on a never-ending stream of patches for quirks. > > This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 > hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and > enable > the feature without the need for quirks. > > Tested on a Logitech M705 mouse that was unsupported before this > change. > > [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: > input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb- > 0000:00:14.0-4/input2:3 > [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 > device connected. > [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected > HID++ 2.0 hi-res scroll wheel > [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel > multiplier = 8 > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 > Signed-off-by: Bastien Nocera <hadess@hadess.net> For anyone on a recent version of Fedora that wants to test it, those packages should work: https://koji.fedoraproject.org/koji/taskinfo?taskID=92008550 Cheers
On 9/14/22 11:41, Bastien Nocera wrote: > On Wed, 2022-09-14 at 15:21 +0200, Bastien Nocera wrote: >> Rather than relying on a never-ending stream of patches for quirks. >> >> This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 >> hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and >> enable >> the feature without the need for quirks. >> >> Tested on a Logitech M705 mouse that was unsupported before this >> change. >> >> [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: >> input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb- >> 0000:00:14.0-4/input2:3 >> [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 >> device connected. >> [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected >> HID++ 2.0 hi-res scroll wheel >> [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel >> multiplier = 8 >> >> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 >> Signed-off-by: Bastien Nocera <hadess@hadess.net> > For anyone on a recent version of Fedora that wants to test it, those > packages should work: > https://koji.fedoraproject.org/koji/taskinfo?taskID=92008550 > > Cheers Using this kernel I tested several Logitech mice - an MX Master 3, which already supported hi-res scrolling in Linux; an M310 and an M185, which have features but no feature for hi-res scrolling; and an old-style M510, which does not have features. I used evtest to show the events that were generated. For these mice the patch does not produce any change in events generated, as expected, both REL_WHEEL and REL_WHEEL_HI_RES events. Peter F. Patel-Schneider
On Thu, 2022-09-15 at 10:23 -0400, Peter F. Patel-Schneider wrote: > > On 9/14/22 11:41, Bastien Nocera wrote: > > On Wed, 2022-09-14 at 15:21 +0200, Bastien Nocera wrote: > > > Rather than relying on a never-ending stream of patches for > > > quirks. > > > > > > This change will detect whether HID++ 1.0 hi-res scroll, HID++ > > > 2.0 > > > hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and > > > enable > > > the feature without the need for quirks. > > > > > > Tested on a Logitech M705 mouse that was unsupported before this > > > change. > > > > > > [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: > > > input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb- > > > 0000:00:14.0-4/input2:3 > > > [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ > > > 4.5 > > > device connected. > > > [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: > > > Detected > > > HID++ 2.0 hi-res scroll wheel > > > [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel > > > multiplier = 8 > > > > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 > > > Signed-off-by: Bastien Nocera <hadess@hadess.net> > > For anyone on a recent version of Fedora that wants to test it, > > those > > packages should work: > > https://koji.fedoraproject.org/koji/taskinfo?taskID=92008550 > > > > Cheers > > > > Using this kernel I tested several Logitech mice - an MX Master 3, > which > already supported hi-res scrolling in Linux; an M310 and an M185, > which have > features but no feature for hi-res scrolling; and an old-style M510, > which > does not have features. I used evtest to show the events that were > generated. For these mice the patch does not produce any change in > events > generated, as expected, both REL_WHEEL and REL_WHEEL_HI_RES events. In the future, it would be awesome if you could mention the tested-by tag as mentioned here: https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes As the tree maintainer can then use it directly when merging the patch in their tree. So, for Jiri or Benjamin: Tested-by: Peter F. Patel-Schneider <pfpschneider@gmail.com> :) Thanks for the testing, much appreciated!
On Wed, 14 Sept 2022 at 14:22, Bastien Nocera <hadess@hadess.net> wrote: > > Rather than relying on a never-ending stream of patches for quirks. > > This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 > hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and enable > the feature without the need for quirks. > > Tested on a Logitech M705 mouse that was unsupported before this change. > > [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb-0000:00:14.0-4/input2:3 > [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 device connected. > [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected HID++ 2.0 hi-res scroll wheel > [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel multiplier = 8 > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 > Signed-off-by: Bastien Nocera <hadess@hadess.net> > --- > drivers/hid/hid-logitech-hidpp.c | 118 ++++++++++++++++--------------- > 1 file changed, 61 insertions(+), 57 deletions(-) Ah, I'd been wanting to do this in my initial implementation, but couldn't work it out for some reason. Good to see the need for the quirks list replaced! Reviewed-by: Harry Cutts <hcutts@chromium.org>
On Wed, Sep 14, 2022 at 3:21 PM Bastien Nocera <hadess@hadess.net> wrote: > > Rather than relying on a never-ending stream of patches for quirks. > > This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 > hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and enable > the feature without the need for quirks. > > Tested on a Logitech M705 mouse that was unsupported before this change. > > [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb-0000:00:14.0-4/input2:3 > [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 device connected. > [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected HID++ 2.0 hi-res scroll wheel > [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel multiplier = 8 > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 > Signed-off-by: Bastien Nocera <hadess@hadess.net> > --- Added the tested-by line from Peter and applied to for-6.1/logitech in hid.git Cheers, Benjamin > drivers/hid/hid-logitech-hidpp.c | 118 ++++++++++++++++--------------- > 1 file changed, 61 insertions(+), 57 deletions(-) > > diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c > index 74013d0e0a24..5f8261c7b74c 100644 > --- a/drivers/hid/hid-logitech-hidpp.c > +++ b/drivers/hid/hid-logitech-hidpp.c > @@ -74,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click, > #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) > #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) > #define HIDPP_QUIRK_UNIFYING BIT(25) > -#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26) > -#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) > -#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) > -#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) > -#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30) > -#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(31) > +#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26) > +#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27) > +#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28) > > /* These are just aliases for now */ > #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS > #define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS > > /* Convenience constant to check for any high-res support. */ > -#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ > - HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \ > - HIDPP_QUIRK_HI_RES_SCROLL_X2121) > +#define HIDPP_CAPABILITY_HI_RES_SCROLL (HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL | \ > + HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \ > + HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) > > #define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT > > @@ -99,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click, > #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) > #define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5) > #define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6) > +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL BIT(7) > +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL BIT(8) > +#define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL BIT(9) > > #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) > > @@ -3418,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) > int ret; > u8 multiplier = 1; > > - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) { > + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) { > ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false); > if (ret == 0) > ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier); > - } else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) { > + } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) { > ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true, > &multiplier); > - } else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */ { > + } else /* if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL) */ { > ret = hidpp10_enable_scrolling_acceleration(hidpp); > multiplier = 8; > } > @@ -3440,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) > return 0; > } > > +static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) > +{ > + int ret; > + unsigned long capabilities; > + > + capabilities = hidpp->capabilities; > + > + if (hidpp->protocol_major >= 2) { > + u8 feature_index; > + u8 feature_type; > + > + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL, > + &feature_index, &feature_type); > + if (!ret) { > + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL; > + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n"); > + return 0; > + } > + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HI_RESOLUTION_SCROLLING, > + &feature_index, &feature_type); > + if (!ret) { > + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL; > + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n"); > + } > + } else { > + struct hidpp_report response; > + > + ret = hidpp_send_rap_command_sync(hidpp, > + REPORT_ID_HIDPP_SHORT, > + HIDPP_GET_REGISTER, > + HIDPP_ENABLE_FAST_SCROLL, > + NULL, 0, &response); > + if (!ret) { > + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL; > + hid_dbg(hidpp->hid_dev, "Detected HID++ 1.0 fast scroll\n"); > + } > + } > + > + if (hidpp->capabilities == capabilities) > + hid_dbg(hidpp->hid_dev, "Did not detect HID++ hi-res scrolling hardware support\n"); > + return 0; > +} > + > /* -------------------------------------------------------------------------- */ > /* Generic HID++ devices */ > /* -------------------------------------------------------------------------- */ > @@ -3694,8 +3737,9 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, > * cases we must return early (falling back to default behaviour) to > * avoid a crash in hidpp_scroll_counter_handle_scroll. > */ > - if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 > - || hidpp->input == NULL || counter->wheel_multiplier == 0) > + if (!(hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) > + || value == 0 || hidpp->input == NULL > + || counter->wheel_multiplier == 0) > return 0; > > hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value); > @@ -3927,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) > } > > hidpp_initialize_battery(hidpp); > + hidpp_initialize_hires_scroll(hidpp); > > /* forward current battery state */ > if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { > @@ -3946,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) > if (hidpp->battery.ps) > power_supply_changed(hidpp->battery.ps); > > - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) > + if (hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) > hi_res_scroll_enable(hidpp); > > if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input) > @@ -4257,42 +4302,9 @@ static const struct hid_device_id hidpp_devices[] = { > HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, > USB_DEVICE_ID_LOGITECH_T651), > .driver_data = HIDPP_QUIRK_CLASS_WTP }, > - { /* Mouse Logitech Anywhere MX */ > - LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, > - { /* Mouse Logitech Cube */ > - LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, > - { /* Mouse Logitech M335 */ > - LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech M515 */ > - LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, > { /* Mouse logitech M560 */ > LDJ_DEVICE(0x402d), > - .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 > - | HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, > - { /* Mouse Logitech M705 (firmware RQM17) */ > - LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, > - { /* Mouse Logitech M705 (firmware RQM67) */ > - LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech M720 */ > - LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech MX Anywhere 2 */ > - LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech MX Anywhere 2S */ > - LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech MX Master */ > - LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech MX Master 2S */ > - LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech MX Master 3 */ > - LDJ_DEVICE(0x4082), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* Mouse Logitech Performance MX */ > - LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, > + .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, > { /* Keyboard logitech K400 */ > LDJ_DEVICE(0x4024), > .driver_data = HIDPP_QUIRK_CLASS_K400 }, > @@ -4353,14 +4365,6 @@ static const struct hid_device_id hidpp_devices[] = { > { /* MX5500 keyboard over Bluetooth */ > HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), > .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, > - { /* MX Master mouse over Bluetooth */ > - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012), > - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e), > - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > - { /* MX Master 3 mouse over Bluetooth */ > - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023), > - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, > > { /* And try to enable HID++ for all the Logitech Bluetooth devices */ > HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) }, > -- > 2.37.3 >
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 74013d0e0a24..5f8261c7b74c 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -74,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) #define HIDPP_QUIRK_UNIFYING BIT(25) -#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) -#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) -#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30) -#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(31) +#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26) +#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27) +#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28) /* These are just aliases for now */ #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS #define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS /* Convenience constant to check for any high-res support. */ -#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ - HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \ - HIDPP_QUIRK_HI_RES_SCROLL_X2121) +#define HIDPP_CAPABILITY_HI_RES_SCROLL (HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL | \ + HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \ + HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) #define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT @@ -99,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) #define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5) #define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6) +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL BIT(7) +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL BIT(8) +#define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL BIT(9) #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) @@ -3418,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) int ret; u8 multiplier = 1; - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) { + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) { ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false); if (ret == 0) ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier); - } else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) { + } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) { ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true, &multiplier); - } else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */ { + } else /* if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL) */ { ret = hidpp10_enable_scrolling_acceleration(hidpp); multiplier = 8; } @@ -3440,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) return 0; } +static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) +{ + int ret; + unsigned long capabilities; + + capabilities = hidpp->capabilities; + + if (hidpp->protocol_major >= 2) { + u8 feature_index; + u8 feature_type; + + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL, + &feature_index, &feature_type); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n"); + return 0; + } + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HI_RESOLUTION_SCROLLING, + &feature_index, &feature_type); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n"); + } + } else { + struct hidpp_report response; + + ret = hidpp_send_rap_command_sync(hidpp, + REPORT_ID_HIDPP_SHORT, + HIDPP_GET_REGISTER, + HIDPP_ENABLE_FAST_SCROLL, + NULL, 0, &response); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 1.0 fast scroll\n"); + } + } + + if (hidpp->capabilities == capabilities) + hid_dbg(hidpp->hid_dev, "Did not detect HID++ hi-res scrolling hardware support\n"); + return 0; +} + /* -------------------------------------------------------------------------- */ /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ @@ -3694,8 +3737,9 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, * cases we must return early (falling back to default behaviour) to * avoid a crash in hidpp_scroll_counter_handle_scroll. */ - if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 - || hidpp->input == NULL || counter->wheel_multiplier == 0) + if (!(hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) + || value == 0 || hidpp->input == NULL + || counter->wheel_multiplier == 0) return 0; hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value); @@ -3927,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) } hidpp_initialize_battery(hidpp); + hidpp_initialize_hires_scroll(hidpp); /* forward current battery state */ if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { @@ -3946,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) if (hidpp->battery.ps) power_supply_changed(hidpp->battery.ps); - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) + if (hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) hi_res_scroll_enable(hidpp); if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input) @@ -4257,42 +4302,9 @@ static const struct hid_device_id hidpp_devices[] = { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651), .driver_data = HIDPP_QUIRK_CLASS_WTP }, - { /* Mouse Logitech Anywhere MX */ - LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, - { /* Mouse Logitech Cube */ - LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, - { /* Mouse Logitech M335 */ - LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech M515 */ - LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, { /* Mouse logitech M560 */ LDJ_DEVICE(0x402d), - .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 - | HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, - { /* Mouse Logitech M705 (firmware RQM17) */ - LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, - { /* Mouse Logitech M705 (firmware RQM67) */ - LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech M720 */ - LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Anywhere 2 */ - LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Anywhere 2S */ - LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master */ - LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master 2S */ - LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master 3 */ - LDJ_DEVICE(0x4082), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech Performance MX */ - LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, + .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, { /* Keyboard logitech K400 */ LDJ_DEVICE(0x4024), .driver_data = HIDPP_QUIRK_CLASS_K400 }, @@ -4353,14 +4365,6 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX5500 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, - { /* MX Master mouse over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* MX Master 3 mouse over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, { /* And try to enable HID++ for all the Logitech Bluetooth devices */ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) },
Rather than relying on a never-ending stream of patches for quirks. This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and enable the feature without the need for quirks. Tested on a Logitech M705 mouse that was unsupported before this change. [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb-0000:00:14.0-4/input2:3 [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 device connected. [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected HID++ 2.0 hi-res scroll wheel [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel multiplier = 8 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 Signed-off-by: Bastien Nocera <hadess@hadess.net> --- drivers/hid/hid-logitech-hidpp.c | 118 ++++++++++++++++--------------- 1 file changed, 61 insertions(+), 57 deletions(-)