48 lines
1.9 KiB
Python
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)
|