diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py index e933f5ad..dae24921 100644 --- a/lib/logitech_receiver/diversion.py +++ b/lib/logitech_receiver/diversion.py @@ -47,6 +47,7 @@ else: import evdev from .common import NamedInt +from .hidpp20 import Hidpp20 from .hidpp20 import SupportedFeature from .special_keys import CONTROL @@ -1304,6 +1305,11 @@ class Set(Action): if setting is None: logger.warning("Set action: setting %s is not the name of a setting for %s", self.args[1], dev.name) return None + if setting.name == "change-host": + try: + Hidpp20().get_host_names(dev) + except Exception: + logger.debug("Set action: failed to refresh host names before change-host write", exc_info=True) args = setting.acceptable(self.args[2:], setting.read()) if args is None: logger.warning( @@ -1487,6 +1493,15 @@ def process_notification(device, notification: HIDPPNotification, feature) -> No if notification.data[4] <= 0x01: # when wheel starts, zero out last movement thumb_wheel_displacement = 0 thumb_wheel_displacement += signed(notification.data[0:2]) + elif feature == SupportedFeature.CHANGE_HOST and len(notification.data) >= 2: + if 1 <= notification.data[0] <= 3 and notification.data[1] == 0: + host = notification.data[0] + key_down = CONTROL["Host_Switch_Channel_" + str(host)] + logger.debug("mapping change host notification into key %s", key_down) + elif notification.data[0] == 0 and notification.data[1] <= 2: + host = notification.data[1] + 1 + key_down = CONTROL["Host_Switch_Channel_" + str(host)] + logger.debug("mapping change host notification into key %s", key_down) GLib.idle_add(evaluate_rules, feature, notification, device) diff --git a/tests/logitech_receiver/test_diversion.py b/tests/logitech_receiver/test_diversion.py index 70aba163..e22a8224 100644 --- a/tests/logitech_receiver/test_diversion.py +++ b/tests/logitech_receiver/test_diversion.py @@ -111,6 +111,7 @@ def test_feature(): (SupportedFeature.MKEYS, [0x01, 0x02, 0x03, 0x04]), (SupportedFeature.MR, [0x01, 0x02, 0x03, 0x04]), (SupportedFeature.THUMB_WHEEL, [0x01, 0x02, 0x03, 0x04, 0x05]), + (SupportedFeature.CHANGE_HOST, [0x00, 0x01, 0x00, 0x00]), (SupportedFeature.DEVICE_UNIT_ID, [0x01, 0x02, 0x03, 0x04, 0x05]), ], ) @@ -125,3 +126,27 @@ def test_process_notification(feature, data): ) diversion.process_notification(device_mock, notification, feature) + + +@pytest.mark.parametrize( + "data, key_name", + [ + (b"\x01\x00\x00\x00", "Host Switch Channel 1"), + (b"\x02\x00\x00\x00", "Host Switch Channel 2"), + (b"\x00\x01\x00\x00", "Host Switch Channel 2"), + ], +) +def test_process_change_host_notification_maps_to_key_press(data, key_name): + device_mock = mock.Mock() + notification = HIDPPNotification( + report_id=0x01, + devnumber=1, + sub_id=0x13, + address=0x00, + data=data, + ) + + diversion.process_notification(device_mock, notification, SupportedFeature.CHANGE_HOST) + + condition = diversion.Key([key_name, "pressed"]) + assert condition.evaluate(SupportedFeature.CHANGE_HOST, notification, device_mock, True)