Solaar/lib/logitech_receiver/device_quirks.py

48 lines
1.9 KiB
Python

"""Per-device-model quirks.
Keyed by ``device.modelId``, which Logitech composes by concatenating every
transport-specific PID (btid + btleid + wpid + usbid) for a single physical
model. That makes one entry cover the same device regardless of how it is
currently connected — no transport-aliasing gotchas.
Quirks are hand-curated. Devices do not self-report behaviors like "this
firmware ignores the bytes I wrote", so each entry is observation-derived.
Keep entries narrow and document the observation in a comment.
"""
from __future__ import annotations
# Quirk keys are named after the doc-canonical feature/function path so a
# grep for the HID++ feature name (e.g. "RGBEffects", "NvConfig") lands here.
#
# Default-allow: each quirk lists what is KNOWN to be broken or ignored on
# that device model. Unlisted models / unlisted entries get the full UI.
#
# rgb_effects_nvconfig_colors_inert
# Feature 0x8071 RGBEffects, Function 3 NvConfig — cap-id → set of
# color slot names ({"color1", "color2"}) whose bytes the firmware
# accepts but does not visibly apply. UI hides color pickers for
# slots in the set.
QUIRKS: dict[str, dict[str, object]] = {
# G502 X PLUS — RGBEffects NvConfig startup effect (cap 0x0001): color
# bytes are entirely ignored; only the enabled flag is honored. Shutdown
# cap (0x0040) is not supported and is suppressed via build()-time probe.
"4099C0950000": {
"rgb_effects_nvconfig_colors_inert": {
0x0001: {"color1", "color2"},
},
},
}
def get(device, key, default=None):
"""Look up a quirk by key for the device's model.
Returns ``default`` when either the model has no quirks entry or the
entry lacks the requested key.
"""
model_id = getattr(device, "modelId", None)
if not model_id:
return default
return QUIRKS.get(model_id, {}).get(key, default)