From 360c92f6b0761aa91098a57eee2b7230fa93ddc8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Mar 2017 14:16:09 -0300 Subject: [PATCH 1/4] Add support for CLI show to display High Res Wheel settings Add support for the high resolution wheel found on MX Anywhere 2. Signed-off-by: Mauro Carvalho Chehab --- lib/logitech_receiver/hidpp20.py | 27 +++++++++++++++++++++++++++ lib/solaar/cli/show.py | 25 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py index 7faff999..8b441b6f 100644 --- a/lib/logitech_receiver/hidpp20.py +++ b/lib/logitech_receiver/hidpp20.py @@ -477,3 +477,30 @@ def get_mouse_pointer_info(device): 'suggest_os_ballistics': suggest_os_ballistics, 'suggest_vertical_orientation': suggest_vertical_orientation } + +def get_hires_wheel(device): + caps = feature_request(device, FEATURE.HIRES_WHEEL, 0x00) + mode = feature_request(device, FEATURE.HIRES_WHEEL, 0x10) + ratchet = feature_request(device, FEATURE.HIRES_WHEEL, 0x030) + + + if caps and mode and ratchet: + # Parse caps + multi, flags = _unpack('!BB', caps[:2]) + + has_invert = (flags & 0x08) != 0 + has_ratchet = (flags & 0x04) != 0 + + # Parse mode + wheel_mode, reserved = _unpack('!BB', mode[:2]) + + target = (wheel_mode & 0x01) != 0 + res = (wheel_mode & 0x02) != 0 + inv = (wheel_mode & 0x04) != 0 + + # Parse Ratchet switch + ratchet_mode, reserved = _unpack('!BB', ratchet[:2]) + + ratchet = (ratchet_mode & 0x01) != 0 + + return multi, has_invert, has_ratchet, inv, res, target, ratchet diff --git a/lib/solaar/cli/show.py b/lib/solaar/cli/show.py index e69c2a01..d1c3f7ac 100644 --- a/lib/solaar/cli/show.py +++ b/lib/solaar/cli/show.py @@ -93,6 +93,31 @@ def _print_device(dev): flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print (' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) + if feature == _hidpp20.FEATURE.HIRES_WHEEL: + wheel = _hidpp20.get_hires_wheel(dev) + if wheel: + multi, has_invert, has_switch, inv, res, target, ratchet = wheel + print(" Multiplier: %s" % multi) + if has_invert: + print(" Has invert") + if inv: + print(" Inverse wheel motion") + else: + print(" Normal wheel motion") + if has_switch: + print(" Has ratchet switch") + if ratchet: + print(" Normal wheel mode") + else: + print(" Free wheel mode") + if res: + print(" High resolution mode") + else: + print(" Low resolution mode") + if target: + print(" HID++ notification") + else: + print(" HID notification") if dev.online and dev.keys: print (' Has %d reprogrammable keys:' % len(dev.keys)) From 7078750a3f1b1b1c8ee19ac056f23d4963c32b44 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Mar 2017 16:53:48 -0300 Subject: [PATCH 2/4] MX Anywhere2: Correct feature Smooth Scrool Set wrongly to HI_RES_SCROLLING. Correct it to HIRES_WHEEL as reported by MX Anywhere2. relates to #283 Signed-off-by: Josenivaldo Benito Jr --- lib/logitech_receiver/descriptors.py | 4 +- lib/logitech_receiver/settings_templates.py | 41 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/logitech_receiver/descriptors.py b/lib/logitech_receiver/descriptors.py index 3e2bbd1f..c2a415f6 100644 --- a/lib/logitech_receiver/descriptors.py +++ b/lib/logitech_receiver/descriptors.py @@ -283,7 +283,9 @@ _D('Anywhere Mouse MX', codename='Anywhere MX', protocol=1.0, wpid='1017', ) _D('Anywhere Mouse MX 2', codename='Anywhere MX 2', protocol=4.5, wpid='404A', settings=[ - _FS.smooth_scroll(), + _FS.hires_smooth_invert(), + _FS.hires_smooth_resolution(), + _FS.hires_smooth_hid(), ], ) _D('Performance Mouse MX', codename='Performance MX', protocol=1.0, wpid='101A', diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index 6604a147..e7d64f54 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -118,6 +118,12 @@ def feature_range(name, feature, min_value, max_value, _SMOOTH_SCROLL = ('smooth-scroll', _("Smooth Scrolling"), _("High-sensitivity mode for vertical scroll with the wheel.")) +_HIRES_INV = ('hires-smooth-invert', _("High Resolution Wheel Invert"), + _("High-sensitivity wheel invert mode for vertical scroll.")) +_HIRES_RES = ('hires-smooth-resolution', _("Wheel Resolution"), + _("High-sensitivity mode for vertical scroll with the wheel.")) +_HIRES_TGT = ('hires-smooth-hid', _("High Resolution HID++ notification"), + _("High-sensitivity HID++ notification for the wheel.")) _SIDE_SCROLL = ('side-scroll', _("Side Scrolling"), _("When disabled, pushing the wheel sideways sends custom button events\n" "instead of the standard side-scrolling events.")) @@ -184,6 +190,29 @@ def _feature_lowres_smooth_scroll(): return feature_toggle(_SMOOTH_SCROLL[0], _F.LOWRES_WHEEL, label=_SMOOTH_SCROLL[1], description=_SMOOTH_SCROLL[2], device_kind=_DK.mouse) +def _feature_hires_smooth_invert(): + return feature_toggle(_HIRES_INV[0], _F.HIRES_WHEEL, + read_function_id=0x10, + write_function_id=0x20, + true_value=0x04, mask=0x04, + label=_HIRES_INV[1], description=_HIRES_INV[2], + device_kind=_DK.mouse) + +def _feature_hires_smooth_resolution(): + return feature_toggle(_HIRES_RES[0], _F.HIRES_WHEEL, + read_function_id=0x10, + write_function_id=0x20, + true_value=0x02, mask=0x02, + label=_HIRES_RES[1], description=_HIRES_RES[2], + device_kind=_DK.mouse) + +def _feature_hires_smooth_hid(): + return feature_toggle(_HIRES_TGT[0], _F.HIRES_WHEEL, + read_function_id=0x10, + write_function_id=0x20, + true_value=0x01, mask=0x01, + label=_HIRES_TGT[1], description=_HIRES_TGT[2], + device_kind=_DK.mouse) def _feature_smart_shift(): _MIN_SMART_SHIFT_VALUE = 0 @@ -275,6 +304,9 @@ _SETTINGS_LIST = namedtuple('_SETTINGS_LIST', [ 'new_fn_swap', 'smooth_scroll', 'lowres_smooth_scroll', + 'hires_smooth_invert', + 'hires_smooth_resolution', + 'hires_smooth_hid', 'side_scroll', 'dpi', 'pointer_speed', @@ -289,6 +321,9 @@ RegisterSettings = _SETTINGS_LIST( new_fn_swap=None, smooth_scroll=_register_smooth_scroll, lowres_smooth_scroll=None, + hires_smooth_invert=None, + hires_smooth_resolution=None, + hires_smooth_hid=None, side_scroll=_register_side_scroll, dpi=_register_dpi, pointer_speed=None, @@ -301,6 +336,9 @@ FeatureSettings = _SETTINGS_LIST( new_fn_swap=_feature_new_fn_swap, smooth_scroll=_feature_smooth_scroll, lowres_smooth_scroll=_feature_lowres_smooth_scroll, + hires_smooth_invert=_feature_hires_smooth_invert, + hires_smooth_resolution=_feature_hires_smooth_resolution, + hires_smooth_hid=_feature_hires_smooth_hid, side_scroll=None, dpi=_feature_adjustable_dpi, pointer_speed=_feature_pointer_speed, @@ -342,6 +380,9 @@ def check_feature_settings(device, already_known): check_feature(_SMOOTH_SCROLL[0], _F.HI_RES_SCROLLING) check_feature(_SMOOTH_SCROLL[0], _F.LOWRES_WHEEL) + check_feature(_HIRES_INV[0], _F.HIRES_WHEEL, "hires_smooth_invert") + check_feature(_HIRES_RES[0], _F.HIRES_WHEEL, "hires_smooth_resolution") + check_feature(_HIRES_TGT[0], _F.HIRES_WHEEL, "hires_smooth_hid") check_feature(_FN_SWAP[0], _F.FN_INVERSION) check_feature(_FN_SWAP[0], _F.NEW_FN_INVERSION, 'new_fn_swap') check_feature(_DPI[0], _F.ADJUSTABLE_DPI) From 410d100dc619fa3a5d14dda68e23c9c8d8a91f15 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Mar 2017 06:16:37 -0300 Subject: [PATCH 3/4] Add notification for high-resolution Wheel events The event at address 0 is only produced while in HID++ mode. The rachet event (address 0x10) happens on both HID and HID++ modes. Signed-off-by: Mauro Carvalho Chehab --- lib/logitech_receiver/notifications.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/logitech_receiver/notifications.py b/lib/logitech_receiver/notifications.py index 3367d4d9..376e7567 100644 --- a/lib/logitech_receiver/notifications.py +++ b/lib/logitech_receiver/notifications.py @@ -275,4 +275,22 @@ def _process_feature_notification(device, status, n, feature): _log.warn("%s: unknown TOUCH MOUSE %s", device, n) return True + if feature == _F.HIRES_WHEEL: + if (n.address == 0x00): + if _log.isEnabledFor(_INFO): + flags, delta_v = _unpack('>bh', n.data[:3]) + high_res = (flags & 0x10) != 0 + periods = flags & 0x0f + _log.info("%s: WHEEL: res: %d periods: %d delta V:%-3d", device, high_res, periods, delta_v) + return True + elif (n.address == 0x10): + if _log.isEnabledFor(_INFO): + flags = ord(n.data[:1]) + ratchet = flags & 0x01 + _log.info("%s: WHEEL: ratchet: %d", device, ratchet) + return True + else: + _log.warn("%s: unknown WHEEL %s", device, n) + return True + _log.warn("%s: unrecognized %s for feature %s (index %02X)", device, n, feature, n.sub_id) From 801bdfa224bda2993b27886b3572db5fb07b4c84 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Apr 2017 10:44:07 -0300 Subject: [PATCH 4/4] Remove the hid++ high-res wheel notification The best is to make the logitech-hidpp driver to switch to hid++ notification mode when it starts. As we don't want users to mangle with it, let's remove support from it. PS.: I opted to keep this as a separate patch. This way, if anyone needs to add support for it, in order to debug the driver, it is just a matter of reverting this patch. Signed-off-by: Mauro Carvalho Chehab --- lib/logitech_receiver/descriptors.py | 1 - lib/logitech_receiver/settings_templates.py | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/lib/logitech_receiver/descriptors.py b/lib/logitech_receiver/descriptors.py index c2a415f6..3d240551 100644 --- a/lib/logitech_receiver/descriptors.py +++ b/lib/logitech_receiver/descriptors.py @@ -285,7 +285,6 @@ _D('Anywhere Mouse MX 2', codename='Anywhere MX 2', protocol=4.5, wpid='404A', settings=[ _FS.hires_smooth_invert(), _FS.hires_smooth_resolution(), - _FS.hires_smooth_hid(), ], ) _D('Performance Mouse MX', codename='Performance MX', protocol=1.0, wpid='101A', diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index e7d64f54..16ddb063 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -122,8 +122,6 @@ _HIRES_INV = ('hires-smooth-invert', _("High Resolution Wheel Invert"), _("High-sensitivity wheel invert mode for vertical scroll.")) _HIRES_RES = ('hires-smooth-resolution', _("Wheel Resolution"), _("High-sensitivity mode for vertical scroll with the wheel.")) -_HIRES_TGT = ('hires-smooth-hid', _("High Resolution HID++ notification"), - _("High-sensitivity HID++ notification for the wheel.")) _SIDE_SCROLL = ('side-scroll', _("Side Scrolling"), _("When disabled, pushing the wheel sideways sends custom button events\n" "instead of the standard side-scrolling events.")) @@ -206,14 +204,6 @@ def _feature_hires_smooth_resolution(): label=_HIRES_RES[1], description=_HIRES_RES[2], device_kind=_DK.mouse) -def _feature_hires_smooth_hid(): - return feature_toggle(_HIRES_TGT[0], _F.HIRES_WHEEL, - read_function_id=0x10, - write_function_id=0x20, - true_value=0x01, mask=0x01, - label=_HIRES_TGT[1], description=_HIRES_TGT[2], - device_kind=_DK.mouse) - def _feature_smart_shift(): _MIN_SMART_SHIFT_VALUE = 0 _MAX_SMART_SHIFT_VALUE = 50 @@ -306,7 +296,6 @@ _SETTINGS_LIST = namedtuple('_SETTINGS_LIST', [ 'lowres_smooth_scroll', 'hires_smooth_invert', 'hires_smooth_resolution', - 'hires_smooth_hid', 'side_scroll', 'dpi', 'pointer_speed', @@ -323,7 +312,6 @@ RegisterSettings = _SETTINGS_LIST( lowres_smooth_scroll=None, hires_smooth_invert=None, hires_smooth_resolution=None, - hires_smooth_hid=None, side_scroll=_register_side_scroll, dpi=_register_dpi, pointer_speed=None, @@ -338,7 +326,6 @@ FeatureSettings = _SETTINGS_LIST( lowres_smooth_scroll=_feature_lowres_smooth_scroll, hires_smooth_invert=_feature_hires_smooth_invert, hires_smooth_resolution=_feature_hires_smooth_resolution, - hires_smooth_hid=_feature_hires_smooth_hid, side_scroll=None, dpi=_feature_adjustable_dpi, pointer_speed=_feature_pointer_speed, @@ -382,7 +369,6 @@ def check_feature_settings(device, already_known): check_feature(_SMOOTH_SCROLL[0], _F.LOWRES_WHEEL) check_feature(_HIRES_INV[0], _F.HIRES_WHEEL, "hires_smooth_invert") check_feature(_HIRES_RES[0], _F.HIRES_WHEEL, "hires_smooth_resolution") - check_feature(_HIRES_TGT[0], _F.HIRES_WHEEL, "hires_smooth_hid") check_feature(_FN_SWAP[0], _F.FN_INVERSION) check_feature(_FN_SWAP[0], _F.NEW_FN_INVERSION, 'new_fn_swap') check_feature(_DPI[0], _F.ADJUSTABLE_DPI)