fix(cec): support HDMI-CEC display power on Pi 4/5 second micro-HDMI port#3085
fix(cec): support HDMI-CEC display power on Pi 4/5 second micro-HDMI port#3085federicopratto wants to merge 3 commits into
Conversation
|
Thank you for your contribution, but could you please translate this to English? We can't accept contributions with Spanish comments in the code base or the PR. |
vpetersson
left a comment
There was a problem hiding this comment.
Thanks for digging into this — the diagnostics change and the new tests are good. But there's a hard blocker in bin/upgrade_containers.sh plus a couple of things worth confirming before this can land. Details inline.
Summary
- 🔴 The
x86|arm64branch body is a literal...placeholder — it aborts the upgrade (#!/bin/bash -e,...→ command-not-found → exit 127) on every x86/arm64 device, and deletes the logic that strips the/dev/vchiqmount so those boards can boot at all. Must be restored. - 🟡 The primary remap path depends on
cec-ctlbeing installed on the host, which Anthias doesn't manage — on a stock Pi OS host it silently falls back to the old broken behavior. - 🟡 The fallback mounts both
/dev/cec0and/dev/cec1underdevices:, which fails container start if a host exposes only one — andpi4-64is unverified on real hardware. - 🟢 Minor:
cec-ctl --playbackis a mutating probe; Spanish comments in an otherwise-English file.
| sed -i 's|/dev/vchiq:/dev/vchiq|/dev/cec0:/dev/cec0|g' \ | ||
| pi4-64|pi5) | ||
| CEC_DEV="" | ||
| if command -v cec-ctl >/dev/null 2>&1; then |
There was a problem hiding this comment.
🟡 This remap path only triggers when cec-ctl exists on the host. cec-ctl ships in v4l-utils, which isn't installed by default on Raspberry Pi OS, and Anthias is userspace-only (doesn't manage host packages). On a stock Pi host this takes the else fallback — which, per your own comment below, won't work if the live port is /dev/cec1.
So for the majority of real devices this likely degrades to the old broken behavior. Can you confirm whether the target hosts actually ship cec-ctl? If not, the fix's real-world reach is much narrower than the PR implies and should be documented (or the detection moved somewhere that has cec-ctl available).
There was a problem hiding this comment.
Confirmed, and you're right to push on this. Checked our own ansible
playbooks — grep -rn "v4l-utils\|cec-ctl\|cec-utils" ansible/
returns nothing, so Anthias's installer never provisions it. On my
test Pi 5, apt-mark showmanual lists v4l-utils as manually
installed, not part of the base image — I'd installed it myself while
diagnosing this, so a genuinely stock host almost certainly doesn't
have it.
So yes: on a typical install today, this falls through to the
degraded fallback in most cases, same as you suspected. Two ways I
see to actually close that gap rather than just document it:
- Have
upgrade_containers.shinstallv4l-utilsitself on
pi4-64|pi5whencec-ctlis missing — but that crosses the
"Anthias doesn't manage host packages" line you mentioned, so I
don't want to do that without a green light. - Run the
cec-ctlprobe from inside a throwaway container using
the server image instead (addingv4l-utilsto
Dockerfile.server/Dockerfile.test, passing
--device=/dev/cec0 --device=/dev/cec1to adocker run), so
detection never depends on anything installed on the host at all.
(2) feels more in line with the project's existing philosophy, but
it's more surface area than this PR currently touches. Happy to do
whichever you'd rather see — or land this as-is with the limitation
called out explicitly (comment + PR description) and open a
follow-up issue for the container-based probe.
…p mutating CEC probe - Restore the x86|arm64 case body that was accidentally replaced with a placeholder, breaking the upgrade on every non-Pi device. - Guard each /dev/cecN mount in the pi4-64|pi5 fallback path with [ -e ], since devices: entries fail container start if a listed host path doesn't exist and pi4-64 isn't confirmed to always expose both nodes. - Swap cec-ctl --playback for a bare invocation when probing physical address, avoiding the active CEC bus scan / logical-address claim that --playback (and --show-topology) trigger. - Translate inline comments to English for consistency with the rest of the file.
|
|
waiting for the review... |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3085 +/- ##
=========================================
Coverage ? 86.56%
=========================================
Files ? 61
Lines ? 5902
Branches ? 655
=========================================
Hits ? 5109
Misses ? 630
Partials ? 163 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
vpetersson
left a comment
There was a problem hiding this comment.
Follow-up review
Re-reviewed against the current head. Resolved the four threads whose fixes I confirmed in the code (the ... placeholder, the unconditional dual-node mount, the --playback mutating probe, and the Spanish comments). One substantive concern remains open, plus one nit.
🟡 The remap only fires when cec-ctl is on the host — so it doesn't work out-of-the-box for the case it targets
cec-ctl ships in v4l-utils, which Anthias never provisions (grep -rn "v4l-utils\|cec-ctl" ansible/ is empty) and, being userspace-only, doesn't manage. On a stock Raspberry Pi OS host, command -v cec-ctl fails and the code takes the else fallback.
On real Pi 4/5, both /dev/cec0 and /dev/cec1 always exist (one controller per micro-HDMI) regardless of what's plugged in — only the physical address differs. So the fallback mounts both under their real names, the container's cec.init() opens its hard-coded default /dev/cec0, and if the TV is on the second port that adapter is still f.f.f.f → the "CEC error" symptom persists, unchanged from before the PR. The happy path effectively only fires for users who manually installed v4l-utils.
Suggested direction: move the adapter selection into the container, where Anthias owns the toolchain — the cec==0.2.8 lib is already there. Mount both nodes unconditionally (guarded with [[ -e ]]) and have _CEC_SET_SCRIPT / _CEC_QUERY_SCRIPT in src/anthias_server/lib/diagnostics.py iterate the available adapters and pick the one whose physical address isn't f.f.f.f, instead of relying on a host binary that isn't installed. That makes the second-port case work regardless of host packaging and drops the host-side cec-ctl dependency entirely.
🟢 Minor: stale header comment
bin/upgrade_containers.sh:154-164 still says "Pi 5 also exposes /dev/cec1 … so we map both." The primary path no longer maps both — it remaps the single live node to /dev/cec0. Worth updating so the comment matches the new logic.
✅ Correct
pi4-64is the right token (Pi 4 is alwayspi4-64); extendingpi5→pi4-64|pi5is sound — both arevc4-kms-v3d.- The multi-line
MOUNT_REPLsed(\n\1per node, applied to both the server and celeryvchiqlines) is correct GNU-sed, and the template mount lines (docker-compose.yml.tmpl:29,153) match the anchor exactly. cec_available()adding/dev/cec1and the two new tests are consistent.- Idempotent — compose is re-rendered from the template before the
sedeach run, so no accumulation.



Fixes #2863
What this fixes
HDMI-CEC display power (#2886, experimental) still doesn't work on Raspberry Pi 4/5 when the display is connected to the second micro-HDMI port. Symptom: "Display Power (CEC): CEC error" / "Unknown" in System Info, and the Settings buttons do nothing.
Root cause
Pi 4 and Pi 5 each expose two kernel CEC adapters, one per micro-HDMI port (
/dev/cec0,/dev/cec1), but only the port that's actually connected gets a valid physical address — the other one stays atf.f.f.f. The Pythonceclibrary Anthias uses doesn't enumerate both: it specifically looks at/dev/cec0. The fix in #2863 mounts both real paths into the container, but that's not enough — if the TV is on the second port,cec.init()either opens the wrong adapter, or finds nothing at all.Confirmed on hardware (Raspberry Pi 5, kernel 6.18.34-rpt-rpi-2712):
Fix
bin/upgrade_containers.shnow usescec-ctlto detect which of the two/dev/cecNdevices reports a valid physical address, and remaps it to the fixed path/dev/cec0inside the container — regardless of which real index it has on the host. Ifcec-ctlisn't available, it falls back to the previous behavior (mounting both under their real names: degraded, not broken). Thepi5logic is also extended topi4-64, sinceansible/roles/system/templates/config.txt.j2confirms both usevc4-kms-v3d.diagnostics.py::cec_available()now also recognizes/dev/cec1, as a safeguard for the fallback scenario above.Testing
is_on()) and the commands (standby()/power_on()) — the TV physically turns off and on.test_cec_available_true_when_only_cec1_presentintests/test_diagnostics.py— passes (37/37 in the file).test_display_power_section_visible_with_cec1_only(+cec1_stub_devicefixture) intests/test_app.py, following the same pattern as the existing/dev/vchiqtest. I couldn't run it locally due to a Docker infrastructure issue unrelated to this change (Dockerfile rendering for the x86 target); it should run fine in CI — confirmation during review would be appreciated.pi4-64extension is justified by architecture but not verified on real Pi 4 hardware. Confirmation from someone with one on hand is very welcome.Files changed
bin/upgrade_containers.shsrc/anthias_server/lib/diagnostics.pytests/test_diagnostics.pytests/test_app.py