From 3be2d485b0a10101e93dbddc99798eaf74e0fe0e Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Thu, 30 Apr 2026 15:25:56 -0300 Subject: [PATCH] fix(installer): prefer real HDMI EDID during setup --- Cargo.lock | 6 ++--- client/Cargo.toml | 2 +- common/Cargo.toml | 2 +- scripts/install/server.sh | 25 ++++++++++++++++--- server/Cargo.toml | 2 +- .../tests/server_install_script_contract.rs | 16 ++++++++++++ 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 312432a..6a01502 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1652,7 +1652,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "lesavka_client" -version = "0.16.4" +version = "0.16.5" dependencies = [ "anyhow", "async-stream", @@ -1686,7 +1686,7 @@ dependencies = [ [[package]] name = "lesavka_common" -version = "0.16.4" +version = "0.16.5" dependencies = [ "anyhow", "base64", @@ -1698,7 +1698,7 @@ dependencies = [ [[package]] name = "lesavka_server" -version = "0.16.4" +version = "0.16.5" dependencies = [ "anyhow", "base64", diff --git a/client/Cargo.toml b/client/Cargo.toml index 33afe89..41a9fdc 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -4,7 +4,7 @@ path = "src/main.rs" [package] name = "lesavka_client" -version = "0.16.4" +version = "0.16.5" edition = "2024" [dependencies] diff --git a/common/Cargo.toml b/common/Cargo.toml index 73549ec..006346a 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lesavka_common" -version = "0.16.4" +version = "0.16.5" edition = "2024" build = "build.rs" diff --git a/scripts/install/server.sh b/scripts/install/server.sh index c96e72e..7d190d4 100755 --- a/scripts/install/server.sh +++ b/scripts/install/server.sh @@ -614,18 +614,19 @@ prepare_hdmi_detection_boot_state() { } describe_hdmi_connectors() { - local dev name status id + local dev name status id edid_bytes for dev in /sys/class/drm/card*-HDMI-A-*; do [[ -e $dev/status ]] || continue name=$(basename "$dev") status=$(cat "$dev/status" 2>/dev/null || true) id=$(cat "$dev/connector_id" 2>/dev/null || true) - printf ' %s (%s): %s\n' "$(normalize_hdmi_connector "$name")" "${id:-no-id}" "${status:-unknown}" >&2 + edid_bytes=$(wc -c <"$dev/edid" 2>/dev/null || echo 0) + printf ' %s (%s): %s, edid=%sB\n' "$(normalize_hdmi_connector "$name")" "${id:-no-id}" "${status:-unknown}" "${edid_bytes:-0}" >&2 done } detect_connected_hdmi_connector() { - local dev name stable_name status score + local dev name stable_name status score existing increment edid_bytes local best="" best_score=0 best_count=0 declare -A scores=() @@ -639,7 +640,15 @@ detect_connected_hdmi_connector() { stable_name=$(normalize_hdmi_connector "$name") status=$(cat "$dev/status" 2>/dev/null || true) if [[ $status == connected ]]; then - scores[$stable_name]=$(( ${scores[$stable_name]:-0} + 1 )) + increment=1 + # A boot-forced HDMI connector also reports "connected" on Raspberry Pi, + # even when no sink is present. Real EDID is stronger evidence than the + # status bit, so prefer it before falling back to older install state. + edid_bytes=$(wc -c <"$dev/edid" 2>/dev/null || echo 0) + if [[ ${edid_bytes:-0} =~ ^[0-9]+$ ]] && (( edid_bytes > 0 )); then + increment=20 + fi + scores[$stable_name]=$(( ${scores[$stable_name]:-0} + increment )) fi done sleep 0.2 @@ -666,6 +675,14 @@ detect_connected_hdmi_connector() { return 0 fi + existing=$(read_existing_hdmi_connector) + if [[ -n $existing && ${scores[$existing]:-0} -eq $best_score ]]; then + echo "⚠️ multiple HDMI connectors are equally connected; preserving existing LESAVKA_HDMI_CONNECTOR=$existing." >&2 + describe_hdmi_connectors + printf '%s\n' "$existing" + return 0 + fi + echo "❌ multiple HDMI connectors are equally connected; refusing to guess." >&2 describe_hdmi_connectors echo " Disconnect the non-target HDMI output or run once with LESAVKA_HDMI_CONNECTOR=HDMI-A-N." >&2 diff --git a/server/Cargo.toml b/server/Cargo.toml index 1e29a85..13e5eec 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -10,7 +10,7 @@ bench = false [package] name = "lesavka_server" -version = "0.16.4" +version = "0.16.5" edition = "2024" autobins = false diff --git a/testing/tests/server_install_script_contract.rs b/testing/tests/server_install_script_contract.rs index 11eba18..03d5fa0 100644 --- a/testing/tests/server_install_script_contract.rs +++ b/testing/tests/server_install_script_contract.rs @@ -198,6 +198,22 @@ fn server_install_pins_hdmi_camera_and_display_defaults() { SERVER_INSTALL.contains("validate_server_ready"), "install script should verify that lesavka-server reaches a running state" ); + assert!( + SERVER_INSTALL.contains("edid_bytes=$(wc -c <\"$dev/edid\""), + "HDMI auto-detection should count real EDID bytes instead of trusting sysfs file size" + ); + assert!( + SERVER_INSTALL.contains("(( edid_bytes > 0 ))"), + "HDMI auto-detection should prefer a connector with real EDID over a boot-forced phantom connection" + ); + assert!( + SERVER_INSTALL.contains("preserving existing LESAVKA_HDMI_CONNECTOR"), + "HDMI auto-detection should preserve the prior connector when physical evidence is still tied" + ); + assert!( + SERVER_INSTALL.contains("edid=%sB"), + "ambiguous HDMI diagnostics should show EDID evidence for operator debugging" + ); assert!( SERVER_INSTALL.contains("active and listening"), "install script should require the TCP listener before declaring server readiness"