Add startup animation toggle for COLOR_LED_EFFECTS devices

The 0x8070 V1+ NvConfig (GetNvConfig/SetNvConfig, funcs 4/5) carries a
startup-effect toggle under capability 0x0001 — a pure on/off switch
(0x01/0x02) with no color payload, unlike the 0x8071 NvConfig boot
effects; the boot color comes from the NV-persisted zone effect.
GetNvConfig echoes the capability ID ahead of the value.

Wire format captured from G HUB driving a G560 (usbmon) and the
round-trip hardware-verified.  Build probes the capability and
suppresses the setting on devices that NACK it.  The G560's only other
NvConfig capability is 0x0002, which on 0x8071 devices causes a
firmware animation-loop lockup — deliberately not exposed.
This commit is contained in:
Ken Sanislo 2026-07-16 20:52:13 -07:00
parent 0cc048cdf6
commit bdc17e9fb5
2 changed files with 34 additions and 0 deletions

View File

@ -3330,6 +3330,34 @@ class LEDZoneSetting(settings.Setting):
return cls.setup(device, 0xE0, 0x30, b"")
class LEDStartupAnimation(settings.Setting):
"""Startup effect on/off via 0x8070 NvConfig (funcs 4/5, cap 0x0001, V1+).
A pure toggle with no color payload; GetNvConfig echoes the capability ID
ahead of the value.
"""
name = "led_startup_animation"
label = _("Startup Animation")
description = (
_("Firmware-played animation when the device powers on.") + "\n" + _("Setting persists on the device (non-volatile).")
)
feature = _F.COLOR_LED_EFFECTS
min_version = 1
rw_options = {"read_fnid": 0x40, "write_fnid": 0x50, "prefix": b"\x00\x01"} # NvConfig capability 0x0001
validator_class = settings_validator.BooleanValidator
validator_options = {"true_value": 0x01, "false_value": 0x02, "read_skip_byte_count": 2}
@classmethod
def build(cls, device):
try: # gate on the device actually supporting the capability
if not device.feature_request(cls.feature, 0x40, b"\x00\x01"):
return None
except exceptions.FeatureCallError:
return None
return super().build(device)
class RGBControl(settings.Setting):
name = "rgb_control"
label = _("LED Control")
@ -4503,6 +4531,7 @@ SETTINGS: list[settings.Setting] = [
Backlight3,
LEDControl,
LEDZoneSetting,
LEDStartupAnimation,
RGBControl,
RGBEffectSetting,
PerKeyLighting,

View File

@ -286,6 +286,11 @@ simple_tests = [
fake_hidpp.Response("00", 0x0470),
fake_hidpp.Response("01", 0x0480, "01"),
),
Setup( # NvConfig startup toggle: GetNvConfig echoes the cap ID; 0x01 on / 0x02 off
FeatureTest(settings_templates.LEDStartupAnimation, False, True, version=5),
fake_hidpp.Response("00010200000000000000", 0x0440, "0001"),
fake_hidpp.Response("000101", 0x0450, "000101"),
),
Setup(
FeatureTest(
settings_templates.LEDZoneSetting,