654 lines
28 KiB
Python
654 lines
28 KiB
Python
## Copyright (C) 2024 Solaar Contributors https://pwr-solaar.github.io/Solaar/
|
|
##
|
|
## This program is free software; you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation; either version 2 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License along
|
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
"""The tests work by creating a faked device (from the hidpp module) that uses provided data as responses to HID++ commands.
|
|
The device uses some methods from the real device to set up data structures that are needed for some tests.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from struct import pack
|
|
from typing import Any
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
|
|
from logitech_receiver import common
|
|
from logitech_receiver import hidpp20
|
|
from logitech_receiver import settings_templates
|
|
from logitech_receiver import special_keys
|
|
from solaar import configuration
|
|
|
|
from . import hidpp
|
|
|
|
# TODO DpiSlidingXY, MouseGesturesXY, SpeedChange
|
|
# TODO Gesture2Gestures, Gesture2Divert, Gesture2Params, MKeyLEDs, Equalizer, LEDZoneSetting
|
|
# TODO future RGB..., RGB..., BrightnessControl
|
|
|
|
|
|
@dataclass
|
|
class RegisterTest:
|
|
sclass: Any
|
|
initial_value: Any = False
|
|
write_value: Any = True
|
|
write_params: str = ""
|
|
|
|
|
|
tests = [
|
|
[
|
|
RegisterTest(settings_templates.RegisterHandDetection, False, True, [b"\x00\x00\x00"]),
|
|
hidpp.Response("000030", 0x8101), # keyboard_hand_detection
|
|
hidpp.Response("000000", 0x8001, "000000"),
|
|
],
|
|
[
|
|
RegisterTest(settings_templates.RegisterHandDetection, True, False, [b"\x00\x00\x30"]),
|
|
hidpp.Response("000000", 0x8101), # keyboard_hand_detection
|
|
hidpp.Response("000030", 0x8001, "000030"),
|
|
],
|
|
[
|
|
RegisterTest(settings_templates.RegisterSmoothScroll, False, True, [b"\x40"]),
|
|
hidpp.Response("00", 0x8101), # mouse_button_flags
|
|
hidpp.Response("40", 0x8001, "40"),
|
|
],
|
|
[
|
|
RegisterTest(settings_templates.RegisterSideScroll, True, False, [b"\x00"]),
|
|
hidpp.Response("02", 0x8101), # mouse_button_flags
|
|
hidpp.Response("00", 0x8001, "00"),
|
|
],
|
|
[
|
|
RegisterTest(settings_templates.RegisterFnSwap, False, True, [b"\x00\x01"]),
|
|
hidpp.Response("0000", 0x8109), # keyboard_fn_swap
|
|
hidpp.Response("0001", 0x8009, "0001"),
|
|
],
|
|
[
|
|
RegisterTest(
|
|
settings_templates._PerformanceMXDpi, common.NamedInt(0x88, "800"), common.NamedInt(0x89, "900"), [b"\x89"]
|
|
),
|
|
hidpp.Response("88", 0x8163), # mouse_dpi
|
|
hidpp.Response("89", 0x8063, "89"),
|
|
],
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("test", tests)
|
|
def test_register_template(test, mocker):
|
|
device = hidpp.Device(responses=test[1:])
|
|
device.persister = configuration._DeviceEntry()
|
|
device.protocol = 1.0
|
|
spy_request = mocker.spy(device, "request")
|
|
|
|
setting = test[0].sclass.build(device)
|
|
value = setting.read(cached=False)
|
|
cached_value = setting.read(cached=True)
|
|
write_value = setting.write(test[0].write_value)
|
|
|
|
assert setting is not None
|
|
assert value == test[0].initial_value
|
|
assert cached_value == test[0].initial_value
|
|
assert write_value == test[0].write_value
|
|
spy_request.assert_called_with(test[0].sclass.register + 0x8000, *test[0].write_params)
|
|
|
|
|
|
@dataclass
|
|
class FeatureTest:
|
|
sclass: Any
|
|
initial_value: Any = False
|
|
write_value: Any = True
|
|
write_fnid: int = 0x10
|
|
write_params: str = ""
|
|
no_reply: Optional[bool] = False
|
|
|
|
|
|
tests = [
|
|
[
|
|
FeatureTest(settings_templates.K375sFnSwap, False, True, 0x10, "FF01"),
|
|
hidpp.Response("060001", 0x0000, "40A3"), # K375_FN_INVERSION
|
|
hidpp.Response("FF0001", 0x0600, "FF"),
|
|
hidpp.Response("FF0101", 0x0610, "FF01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.FnSwap, True, False, 0x10, "00"),
|
|
hidpp.Response("040001", 0x0000, "40A0"), # FN_INVERSION
|
|
hidpp.Response("01", 0x0400),
|
|
hidpp.Response("00", 0x0410, "00"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.NewFnSwap, True, False, 0x10, "00"),
|
|
hidpp.Response("040001", 0x0000, "40A2"), # NEW_FN_INVERSION
|
|
hidpp.Response("01", 0x0400),
|
|
hidpp.Response("00", 0x0410, "00"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight, 0, 5, 0x10, "05"),
|
|
hidpp.Response("060001", 0x0000, "1981"), # BACKLIGHT
|
|
hidpp.Response("00", 0x0600),
|
|
hidpp.Response("05", 0x0610, "05"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2DurationHandsOut, 80, 160, 0x10, "0118FF00200040006000", None),
|
|
hidpp.Response("040003", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011830000000100040006000", 0x0400),
|
|
hidpp.Response("0118FF00200040006000", 0x0410, "0118FF00200040006000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2DurationHandsIn, 320, 160, 0x10, "0118FF00200020006000", None),
|
|
hidpp.Response("040003", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011830000000200040006000", 0x0400),
|
|
hidpp.Response("0118FF00200020006000", 0x0410, "0118FF00200020006000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2DurationPowered, 480, 80, 0x10, "0118FF00200040001000", None),
|
|
hidpp.Response("040003", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011830000000200040006000", 0x0400),
|
|
hidpp.Response("0118FF00200040001000", 0x0410, "0118FF00200040001000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight3, 0x50, 0x70, 0x20, "007009"),
|
|
hidpp.Response("040001", 0x0000, "1983"), # BACKLIGHT3
|
|
hidpp.Response("50", 0x0410),
|
|
hidpp.Response("70", 0x0420, "007009"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.HiResScroll, True, False, 0x10, "00"),
|
|
hidpp.Response("040001", 0x0000, "2120"), # HI_RES_SCROLLING
|
|
hidpp.Response("01", 0x0400),
|
|
hidpp.Response("00", 0x0410, "00"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.LowresMode, False, True, 0x10, "01"),
|
|
hidpp.Response("040001", 0x0000, "2130"), # LOWRES_WHEEL
|
|
hidpp.Response("00", 0x0400),
|
|
hidpp.Response("01", 0x0410, "01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.HiresSmoothInvert, True, False, 0x20, "02"),
|
|
hidpp.Response("040001", 0x0000, "2121"), # HIRES_WHEEL
|
|
hidpp.Response("06", 0x0410),
|
|
hidpp.Response("02", 0x0420, "02"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.HiresSmoothResolution, True, False, 0x20, "04"),
|
|
hidpp.Response("040001", 0x0000, "2121"), # HIRES_WHEEL
|
|
hidpp.Response("06", 0x0410),
|
|
hidpp.Response("04", 0x0420, "04"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.HiresMode, False, True, 0x20, "07"),
|
|
hidpp.Response("040001", 0x0000, "2121"), # HIRES_WHEEL
|
|
hidpp.Response("06", 0x0410),
|
|
hidpp.Response("07", 0x0420, "07"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.PointerSpeed, 0x0100, 0x0120, 0x10, "0120"),
|
|
hidpp.Response("040001", 0x0000, "2205"), # POINTER_SPEED
|
|
hidpp.Response("0100", 0x0400),
|
|
hidpp.Response("0120", 0x0410, "0120"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ThumbMode, True, False, 0x20, "0000"),
|
|
hidpp.Response("040001", 0x0000, "2150"), # THUMB_WHEEL
|
|
hidpp.Response("0100", 0x0410),
|
|
hidpp.Response("0000", 0x0420, "0000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ThumbInvert, False, True, 0x20, "0101"),
|
|
hidpp.Response("040001", 0x0000, "2150"), # THUMB_WHEEL
|
|
hidpp.Response("0100", 0x0410),
|
|
hidpp.Response("0101", 0x0420, "0101"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.DivertCrown, False, True, 0x20, "02"),
|
|
hidpp.Response("040001", 0x0000, "4600"), # CROWN
|
|
hidpp.Response("01", 0x0410),
|
|
hidpp.Response("02", 0x0420, "02"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.CrownSmooth, True, False, 0x20, "0002"),
|
|
hidpp.Response("040001", 0x0000, "4600"), # CROWN
|
|
hidpp.Response("0001", 0x0410),
|
|
hidpp.Response("0002", 0x0420, "0002"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.DivertGkeys, False, True, 0x20, "01"),
|
|
hidpp.Response("040001", 0x0000, "8010"), # GKEY
|
|
hidpp.Response("01", 0x0420, "01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ScrollRatchet, 2, 1, 0x10, "01"),
|
|
hidpp.Response("040001", 0x0000, "2110"), # SMART_SHIFT
|
|
hidpp.Response("02", 0x0400),
|
|
hidpp.Response("01", 0x0410, "01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.SmartShift, 1, 10, 0x10, "000A"),
|
|
hidpp.Response("040001", 0x0000, "2110"), # SMART_SHIFT
|
|
hidpp.Response("0100", 0x0400),
|
|
hidpp.Response("000A", 0x0410, "000A"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.SmartShift, 5, 50, 0x10, "00FF"),
|
|
hidpp.Response("040001", 0x0000, "2110"), # SMART_SHIFT
|
|
hidpp.Response("0005", 0x0400),
|
|
hidpp.Response("00FF", 0x0410, "00FF"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.SmartShiftEnhanced, 5, 50, 0x20, "00FF"),
|
|
hidpp.Response("040001", 0x0000, "2111"), # SMART_SHIFT_ENHANCED
|
|
hidpp.Response("0005", 0x0410),
|
|
hidpp.Response("00FF", 0x0420, "00FF"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.DisableKeyboardKeys, {1: True, 8: True}, {1: False, 8: True}, 0x20, "08"),
|
|
hidpp.Response("040003", 0x0000, "4521"), # KEYBOARD_DISABLE_KEYS
|
|
hidpp.Response("09", 0x0400),
|
|
hidpp.Response("09", 0x0410),
|
|
hidpp.Response("08", 0x0420, "08"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.DualPlatform, 0, 1, 0x20, "01"),
|
|
hidpp.Response("040003", 0x0000, "4530"), # DUALPLATFORM
|
|
hidpp.Response("00", 0x0400),
|
|
hidpp.Response("01", 0x0420, "01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.MRKeyLED, False, True, 0x00, "01"),
|
|
hidpp.Response("040003", 0x0000, "8030"), # MR
|
|
hidpp.Response("01", 0x0400, "01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Sidetone, 5, 0xA, 0x10, "0A"),
|
|
hidpp.Response("040003", 0x0000, "8300"), # SIDETONE
|
|
hidpp.Response("05", 0x0400),
|
|
hidpp.Response("0A", 0x0410, "0A"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ADCPower, 5, 0xA, 0x20, "0A"),
|
|
hidpp.Response("040003", 0x0000, "1F20"), # ADC_MEASUREMENT
|
|
hidpp.Response("05", 0x0410),
|
|
hidpp.Response("0A", 0x0420, "0A"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.LEDControl, 0, 1, 0x80, "01"),
|
|
hidpp.Response("040003", 0x0000, "8070"), # COLOR_LED_EFFECTS
|
|
hidpp.Response("00", 0x0470),
|
|
hidpp.Response("01", 0x0480, "01"),
|
|
],
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("test", tests)
|
|
def test_simple_template(test, mocker):
|
|
setup_responses = [hidpp.Response("010001", 0x0000, "0001"), hidpp.Response("20", 0x0100)]
|
|
device = hidpp.Device(responses=test[1:] + setup_responses)
|
|
device.persister = configuration._DeviceEntry()
|
|
device.features = hidpp20.FeaturesArray(device)
|
|
spy_feature_request = mocker.spy(device, "feature_request")
|
|
|
|
setting = settings_templates.check_feature(device, test[0].sclass)
|
|
value = setting.read(cached=False)
|
|
cached_value = setting.read(cached=True)
|
|
write_value = setting.write(test[0].write_value)
|
|
|
|
assert setting is not None
|
|
assert value == test[0].initial_value
|
|
assert cached_value == test[0].initial_value
|
|
assert write_value == test[0].write_value
|
|
params = bytes.fromhex(test[0].write_params)
|
|
no_reply = {"no_reply": test[0].no_reply} if test[0].no_reply is not None else {}
|
|
spy_feature_request.assert_called_with(test[0].sclass.feature, test[0].write_fnid, params, **no_reply)
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_gethostname(mocker):
|
|
mocker.patch("socket.gethostname", return_value="ABCDEF.foo.org")
|
|
|
|
|
|
tests = [
|
|
[
|
|
FeatureTest(settings_templates.Backlight2, 0xFF, 0x00, 0x10, "0102ff00000000000000", None),
|
|
common.NamedInts(Disabled=0xFF, Enabled=0x00),
|
|
hidpp.Response("040001", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("000201000000000000000000", 0x0400),
|
|
hidpp.Response("010201", 0x0410, "0102ff00000000000000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2, 0x03, 0xFF, 0x10, "0018ff00000000000000", None),
|
|
common.NamedInts(Disabled=0xFF, Automatic=0x01, Manual=0x03),
|
|
hidpp.Response("040001", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011838000000000000000000", 0x0400),
|
|
hidpp.Response("001801", 0x0410, "0018ff00000000000000"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2Level, 0, 3, 0x10, "0118ff03000000000000", None),
|
|
[0, 4],
|
|
hidpp.Response("040003", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011830000000000000000000", 0x0400),
|
|
hidpp.Response("01180103000000000000", 0x0410, "0118ff03000000000000"),
|
|
hidpp.Response("05", 0x0420),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.Backlight2Level, 0, 2, 0x10, "0118ff02000000000000", None),
|
|
[0, 4],
|
|
hidpp.Response("040003", 0x0000, "1982"), # BACKLIGHT2
|
|
hidpp.Response("011830000000000000000000", 0x0400),
|
|
hidpp.Response("01180102000000000000", 0x0410, "0118ff02000000000000"),
|
|
hidpp.Response("05", 0x0420),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.OnboardProfiles, 2, 1, 0x30, "0001", None),
|
|
common.NamedInts(**{"Disabled": 0, "Profile 1": 1, "Profile 2": 2}),
|
|
hidpp.Response("0C0003", 0x0000, "8100"), # ONBOARD_PROFILES
|
|
hidpp.Response("00010100000201FFFFFFFFFFFFFFFFFF", 0x0C50, "00000000"),
|
|
hidpp.Response("000201FFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0C50, "00000004"),
|
|
hidpp.Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0C50, "00000008"),
|
|
hidpp.Response("01", 0x0C20),
|
|
hidpp.Response("0002", 0x0C40),
|
|
hidpp.Response("01", 0x0C10, "01"),
|
|
hidpp.Response("0001", 0x0C30, "0001"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.OnboardProfiles, 1, 0, 0x10, "02", None),
|
|
common.NamedInts(**{"Disabled": 0, "Profile 1": 1, "Profile 2": 2}),
|
|
hidpp.Response("0C0003", 0x0000, "8100"), # ONBOARD_PROFILES
|
|
hidpp.Response("00010100000201FFFFFFFFFFFFFFFFFF", 0x0C50, "00000000"),
|
|
hidpp.Response("000201FFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0C50, "00000004"),
|
|
hidpp.Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0C50, "00000008"),
|
|
hidpp.Response("01", 0x0C20),
|
|
hidpp.Response("0001", 0x0C40),
|
|
hidpp.Response("02", 0x0C10, "02"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ReportRate, 1, 5, 0x20, "05"),
|
|
common.NamedInts(**{"1ms": 1, "2ms": 2, "5ms": 5, "6ms": 6}),
|
|
hidpp.Response("0C0003", 0x0000, "8060"), # REPORT_RATE
|
|
hidpp.Response("33", 0x0C00),
|
|
hidpp.Response("01", 0x0C10),
|
|
hidpp.Response("05", 0x0C20, "05"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ExtendedReportRate, 1, 5, 0x30, "05"),
|
|
common.NamedInts(**{"8ms": 0, "4ms": 1, "500us": 4, "250us": 5}),
|
|
hidpp.Response("0C0003", 0x0000, "8061"), # EXTENDED_REPORT_RATE
|
|
hidpp.Response("33", 0x0C10),
|
|
hidpp.Response("01", 0x0C20),
|
|
hidpp.Response("05", 0x0C30, "05"),
|
|
],
|
|
# [
|
|
# FeatureTest(settings_templates.AdjustableDpi, 800, 400, 0x30, "000190"),
|
|
# common.NamedInts.list([400, 800, 1600]),
|
|
# hidpp.Response("040003", 0x0000, "2201"), # ADJUSTABLE_DPI
|
|
# hidpp.Response("000190032006400000", 0x0410, "000000"),
|
|
# hidpp.Response("000320", 0x0420),
|
|
# hidpp.Response("000190", 0x0430, "000190"),
|
|
# ],
|
|
# [
|
|
# FeatureTest(settings_templates.AdjustableDpi, 256, 512, 0x30, "000200"),
|
|
# common.NamedInts.list([256, 512]),
|
|
# hidpp.Response("040003", 0x0000, "2201"), # ADJUSTABLE_DPI
|
|
# hidpp.Response("000100e10002000000", 0x0410, "000000"),
|
|
# hidpp.Response("000100", 0x0420),
|
|
# hidpp.Response("000200", 0x0430, "000200"),
|
|
# ],
|
|
# [
|
|
# FeatureTest(settings_templates.ExtendedAdjustableDpi, 256, 512, 0x60, "000200"),
|
|
# common.NamedInts.list([256, 512]),
|
|
# hidpp.Response("090000", 0x0000, "2202"), # EXTENDED_ADJUSTABLE_DPI
|
|
# hidpp.Response("000000", 0x0910, "00"), # no y direction
|
|
# hidpp.Response("0000000100e10002000000", 0x0920, "000000"),
|
|
# hidpp.Response("000100", 0x0950),
|
|
# hidpp.Response("000200", 0x0960, "000200"),
|
|
# ],
|
|
# [
|
|
# FeatureTest(settings_templates.ExtendedAdjustableDpi, 0x64, 0x164, 0x60, "0001640164"),
|
|
# common.NamedInts.list([0x064, 0x074, 0x084, 0x0A4, 0x0C4, 0x0E4, 0x0124, 0x0164, 0x01C4]),
|
|
# hidpp.Response("090000", 0x0000, "2202"), # EXTENDED_ADJUSTABLE_DPI
|
|
# hidpp.Response("000001", 0x0910, "00"), # supports y direction
|
|
# hidpp.Response("0000000064E0100084E02000C4E02000", 0x0920, "000000"),
|
|
# hidpp.Response("000001E4E0400124E0400164E06001C4", 0x0920, "000001"),
|
|
# hidpp.Response("00000000000000000000000000000000", 0x0920, "000002"),
|
|
# hidpp.Response("000064", 0x0950),
|
|
# hidpp.Response("0001640164", 0x0960, "0001640164"),
|
|
# ],
|
|
[
|
|
FeatureTest(settings_templates.Multiplatform, 0, 1, 0x30, "FF01"),
|
|
common.NamedInts(**{"MacOS 0.1-0.5": 0, "iOS 0.1-0.7": 1, "Linux 0.2-0.9": 2, "Windows 0.3-0.9": 3}),
|
|
hidpp.Response("040003", 0x0000, "4531"), # MULTIPLATFORM
|
|
hidpp.Response("020004000001", 0x0400),
|
|
hidpp.Response("00FF200000010005", 0x0410, "00"),
|
|
hidpp.Response("01FF400000010007", 0x0410, "01"),
|
|
hidpp.Response("02FF040000020009", 0x0410, "02"),
|
|
hidpp.Response("03FF010000030009", 0x0410, "03"),
|
|
hidpp.Response("FF01", 0x0430, "FF01"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.ChangeHost, 1, 0, 0x10, "00", True),
|
|
common.NamedInts(**{"1:ABCDEF": 0, "2:GHIJKL": 1}),
|
|
hidpp.Response("040003", 0x0000, "1814"), # CHANGE_HOST
|
|
hidpp.Response("050003", 0x0000, "1815"), # HOSTS_INFO
|
|
hidpp.Response("01000200", 0x0500),
|
|
hidpp.Response("000100000600", 0x0510, "00"),
|
|
hidpp.Response("000041424344454600", 0x0530, "0000"),
|
|
hidpp.Response("000100000600", 0x0510, "01"),
|
|
hidpp.Response("00004748494A4B4C00", 0x0530, "0100"),
|
|
hidpp.Response("0201", 0x0400),
|
|
hidpp.Response(True, 0x0410, "00"),
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.BrightnessControl, 0x10, 0x20, 0x20, "0020", False),
|
|
[0, 80],
|
|
hidpp.Response("040003", 0x0000, "8040"), # BRIGHTNESS_CONTROL
|
|
hidpp.Response("00505100000000", 0x0400), # 0 to 80, all acceptable, no separate on/off
|
|
hidpp.Response("10", 0x0410), # brightness 16
|
|
hidpp.Response("0020", 0x0420, "0020"), # set brightness 32
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.BrightnessControl, 0x10, 0x00, 0x20, "0000", False),
|
|
[0, 80],
|
|
hidpp.Response("040003", 0x0000, "8040"), # BRIGHTNESS_CONTROL
|
|
hidpp.Response("00505104000000", 0x0400), # 0 to 80, all acceptable, separate on/off
|
|
hidpp.Response("10", 0x0410), # brightness 16
|
|
hidpp.Response("01", 0x0430), # on
|
|
hidpp.Response("00", 0x0440), # set off
|
|
hidpp.Response("0000", 0x0420, "0000"), # set brightness 0
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.BrightnessControl, 0x00, 0x20, 0x20, "0020", False),
|
|
[0, 80],
|
|
hidpp.Response("040003", 0x0000, "8040"), # BRIGHTNESS_CONTROL
|
|
hidpp.Response("00505104000000", 0x0400), # 0 to 80, all acceptable, separate on/off
|
|
hidpp.Response("10", 0x0410), # brightness 16
|
|
hidpp.Response("00", 0x0430), # off
|
|
hidpp.Response("01", 0x0440), # set on
|
|
hidpp.Response("0020", 0x0420, "0020"), # set brightness 32
|
|
],
|
|
[
|
|
FeatureTest(settings_templates.BrightnessControl, 0x20, 0x08, 0x40, "00", False),
|
|
[0, 80],
|
|
hidpp.Response("040003", 0x0000, "8040"), # BRIGHTNESS_CONTROL
|
|
hidpp.Response("00504104001000", 0x0400), # 16 to 80, all acceptable, separate on/off
|
|
hidpp.Response("20", 0x0410), # brightness 32
|
|
hidpp.Response("01", 0x0430), # on
|
|
hidpp.Response("00", 0x0440, "00"), # set off
|
|
],
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("test", tests)
|
|
def test_variable_template(test, mocker, mock_gethostname):
|
|
setup_responses = [hidpp.Response("010001", 0x0000, "0001"), hidpp.Response("20", 0x0100)]
|
|
device = hidpp.Device(responses=test[2:] + setup_responses)
|
|
device.persister = configuration._DeviceEntry()
|
|
device.features = hidpp20.FeaturesArray(device)
|
|
spy_feature_request = mocker.spy(device, "feature_request")
|
|
|
|
setting = settings_templates.check_feature(device, test[0].sclass)
|
|
print("CH", setting)
|
|
print("CH", setting.choices)
|
|
value = setting.read(cached=False)
|
|
print("CV", value)
|
|
cached_value = setting.read(cached=True)
|
|
write_value = setting.write(test[0].write_value)
|
|
|
|
assert setting is not None
|
|
if isinstance(test[1], common.NamedInts):
|
|
assert len(setting.choices) == len(test[1])
|
|
for setting_choice, expected_choice in zip(setting.choices, test[1]):
|
|
assert setting_choice == expected_choice
|
|
if isinstance(test[1], list):
|
|
assert setting._validator.min_value == test[1][0]
|
|
assert setting._validator.max_value == test[1][1]
|
|
print("VALYE", value, test[0].initial_value)
|
|
assert value == test[0].initial_value
|
|
assert cached_value == test[0].initial_value
|
|
assert write_value == test[0].write_value
|
|
|
|
params = bytes.fromhex(test[0].write_params)
|
|
no_reply = {"no_reply": test[0].no_reply} if test[0].no_reply is not None else {}
|
|
spy_feature_request.assert_called_with(test[0].sclass.feature, test[0].write_fnid, params, **no_reply)
|
|
|
|
|
|
responses_reprog_controls = [
|
|
hidpp.Response("050001", 0x0000, "1B04"), # REPROG_CONTROLS_V4
|
|
hidpp.Response("03", 0x0500),
|
|
hidpp.Response("00500038010001010400000000000000", 0x0510, "00"), # left button
|
|
hidpp.Response("00510039010001010400000000000000", 0x0510, "01"), # right button
|
|
hidpp.Response("00C4009D310003070500000000000000", 0x0510, "02"), # smart shift
|
|
hidpp.Response("00500000000000000000000000000000", 0x0520, "0050"), # left button current
|
|
hidpp.Response("00510000500000000000000000000000", 0x0520, "0051"), # right button current
|
|
hidpp.Response("00C40000000000000000000000000000", 0x0520, "00C4"), # smart shift current
|
|
hidpp.Response("0051000051", 0x0530, "0051000051"), # right button set
|
|
]
|
|
|
|
responses_remappable_action = responses_reprog_controls + [
|
|
hidpp.Response("040001", 0x0000, "1C00"), # PERSISTENT_REMAPPABLE_ACTION
|
|
hidpp.Response("0041", 0x0400),
|
|
hidpp.Response("0201", 0x0410),
|
|
hidpp.Response("02", 0x0400),
|
|
hidpp.Response("0050", 0x0420, "00FF"), # left button
|
|
hidpp.Response("0051", 0x0420, "01FF"), # right button
|
|
hidpp.Response("0050000100500000", 0x0430, "0050FF"), # left button current
|
|
hidpp.Response("0051000100500001", 0x0430, "0051FF"), # right button current
|
|
hidpp.Response("0051FF01005100", 0x0440, "0051FF01005100"), # right button set
|
|
]
|
|
|
|
tests = [
|
|
[
|
|
FeatureTest(
|
|
settings_templates.ReprogrammableKeys, {0x50: 0x50, 0x51: 0x50, 0xC4: 0xC4}, {0x51: 0x51}, 0x30, "0051000051"
|
|
),
|
|
{
|
|
common.NamedInt(0x50, "Left Button"): [0x50, 0x51],
|
|
common.NamedInt(0x51, "Right Button"): [0x51, 0x50],
|
|
common.NamedInt(0xC4, "Smart Shift"): [0xC4, 0x50, 0x51],
|
|
},
|
|
]
|
|
+ responses_reprog_controls,
|
|
[
|
|
FeatureTest(settings_templates.DivertKeys, {0xC4: 0}, {0xC4: 1}, 0x30, "00C4030000"),
|
|
{common.NamedInt(0xC4, "Smart Shift"): [0, 1, 2]},
|
|
]
|
|
+ responses_reprog_controls
|
|
+ [hidpp.Response("00C4030000", 0x0530, "00C4030000")],
|
|
[
|
|
FeatureTest(
|
|
settings_templates.PersistentRemappableAction,
|
|
{80: 16797696, 81: 16797696},
|
|
{0x51: 16797952},
|
|
0x40,
|
|
"0051FF01005100",
|
|
),
|
|
{
|
|
common.NamedInt(80, "Left Button"): special_keys.KEYS_KEYS_CONSUMER,
|
|
common.NamedInt(81, "Right Button"): special_keys.KEYS_KEYS_CONSUMER,
|
|
},
|
|
]
|
|
+ responses_remappable_action,
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("test", tests)
|
|
def test_key_template(test, mocker):
|
|
setup_responses = [hidpp.Response("010001", 0x0000, "0001"), hidpp.Response("20", 0x0100)]
|
|
device = hidpp.Device(responses=test[2:] + setup_responses)
|
|
device.persister = configuration._DeviceEntry()
|
|
device.features = hidpp20.FeaturesArray(device)
|
|
spy_feature_request = mocker.spy(device, "feature_request")
|
|
|
|
setting = settings_templates.check_feature(device, test[0].sclass)
|
|
assert setting is not None
|
|
assert len(setting.choices) == len(test[1])
|
|
for k, v in setting.choices.items():
|
|
assert len(v) == len(test[1][k])
|
|
for setting_key, test_key in zip(v, test[1][k]):
|
|
assert setting_key == test_key
|
|
|
|
value = setting.read(cached=False)
|
|
for k, v in test[0].initial_value.items():
|
|
assert value[k] == v
|
|
|
|
for key, value in test[0].write_value.items():
|
|
write_value = setting.write_key_value(key, value)
|
|
assert write_value == value
|
|
|
|
assert spy_feature_request.call_args_list[-1][0][0] == test[0].sclass.feature
|
|
assert spy_feature_request.call_args_list[-1][0][1] == test[0].write_fnid
|
|
param = b"".join(pack("B", p) if isinstance(p, int) else p for p in spy_feature_request.call_args_list[-1][0][2:])
|
|
assert param == bytes.fromhex(test[0].write_params)
|
|
|
|
|
|
tests = [ # needs settings to be set up!!
|
|
[
|
|
FeatureTest(settings_templates.SpeedChange, 0, 0xED, 0x60, "000200"),
|
|
common.NamedInts(**{"Off": 0, "DPI Change": 0xED}),
|
|
hidpp.Response("040001", 0x0000, "2205"), # POINTER_SPEED
|
|
hidpp.Response("0100", 0x0400),
|
|
hidpp.Response("0120", 0x0410, "0120"),
|
|
hidpp.Response("050001", 0x0000, "1B04"), # REPROG_CONTROLS_V4
|
|
hidpp.Response("01", 0x0500),
|
|
hidpp.Response("00ED009D310003070500000000000000", 0x0510, "00"), # DPI Change
|
|
hidpp.Response("00ED0000000000000000000000000000", 0x0520, "00ED"), # DPI Change current
|
|
],
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("test", tests)
|
|
def XX_action_template(test, mocker): # needs settings to be set up!!
|
|
setup_responses = [hidpp.Response("010001", 0x0000, "0001"), hidpp.Response("20", 0x0100)]
|
|
device = hidpp.Device(responses=test[2:] + setup_responses)
|
|
device.persister = configuration._DeviceEntry()
|
|
device.features = hidpp20.FeaturesArray(device)
|
|
spy_feature_request = mocker.spy(device, "feature_request")
|
|
|
|
setting = settings_templates.check_feature(device, test[0].sclass)
|
|
value = setting.read(cached=False)
|
|
cached_value = setting.read(cached=True)
|
|
write_value = setting.write(test[0].write_value)
|
|
|
|
assert setting is not None
|
|
if isinstance(test[1], common.NamedInts):
|
|
assert len(setting.choices) == len(test[1])
|
|
for setting_choice, expected_choice in zip(setting.choices, test[1]):
|
|
assert setting_choice == expected_choice
|
|
if isinstance(test[1], list):
|
|
assert setting._validator.min_value == test[1][0]
|
|
assert setting._validator.max_value == test[1][1]
|
|
assert value == test[0].initial_value
|
|
assert cached_value == test[0].initial_value
|
|
assert write_value == test[0].write_value
|
|
|
|
params = bytes.fromhex(test[0].write_params)
|
|
no_reply = {"no_reply": test[0].no_reply} if test[0].no_reply is not None else {}
|
|
spy_feature_request.assert_called_with(test[0].sclass.feature, test[0].write_fnid, params, **no_reply)
|