The library answers several settings with a NULL matrix or abort() rather
than an error, so the display service crash-looped (Restart=on-failure)
instead of reaching fallback mode: rows above 64, chain_length above 255
(uint8_t binding setter, documented as "no upper limit"), a misspelled
hardware_mapping, and parallel 2-3 on a single-output mapping, reachable
from the Display form on the default adafruit-hat(-pwm) mapping. #586 only
guarded the Pi 5 subset.
- src/matrix_support.py holds the rules for every board (Options::Validate
ranges, binding integer types, mapping names and outputs from
lib/hardware-mapping.c) plus the Pi 5 ones, and is the one source of the
API's numeric ranges.
- DisplayManager checks them before building options and raises
MatrixSettingsRefused, so a hand-edited config falls back with a logged,
reported reason. Emulator mode only warns.
- The config API refuses them with a 400 naming the setting; combinations
are checked against stored values but reported only when the request
sets a field involved.
- The hardware status file gains "cause" (settings/library/forced). The
fallback log and Display banner give the Pi 5 rebuild hint only for a
library failure instead of rebuild + gpio_slowdown advice for every
failure; one Pi 5 slowdown recommendation (1-3, start at 1).
- The Display form offers classic/classic-pi1 and orientation 90/270 and
renders any other stored mapping selected with a warning, so an
unrelated save no longer rewrites them; the API accepts 90/270.
Audit findings F03, F16, F19, F21.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>