install: detect live uac descriptor drift

This commit is contained in:
Brad Stein 2026-05-12 14:39:09 -03:00
parent cf89b15573
commit 42579d6484
2 changed files with 55 additions and 2 deletions

View File

@ -560,6 +560,33 @@ live_uvc_descriptor_matches_request() {
[[ "$(cat "$frame_root/dwDefaultFrameInterval" 2>/dev/null || true)" == "${LESAVKA_UVC_INTERVAL:-333333}" ]]
}
live_uac_descriptor_matches_request() {
if [[ -n ${LESAVKA_DISABLE_UAC:-} ]]; then
[[ ! -d /sys/kernel/config/usb_gadget/lesavka/functions/uac2.usb0 ]]
return $?
fi
local function_root=/sys/kernel/config/usb_gadget/lesavka/functions/uac2.usb0
[[ -d "$function_root" ]] || return 1
local expected_mixer=0
if [[ ${LESAVKA_UAC_HOST_MIXER_CONTROLS:-0} == 1 ]]; then
expected_mixer=1
fi
for attr in p_volume_present p_mute_present c_volume_present c_mute_present; do
[[ -r "$function_root/$attr" ]] || return 1
[[ "$(cat "$function_root/$attr" 2>/dev/null || true)" == "$expected_mixer" ]] || return 1
done
[[ "$(cat "$function_root/p_chmask" 2>/dev/null || true)" == "3" ]] || return 1
[[ "$(cat "$function_root/c_chmask" 2>/dev/null || true)" == "3" ]] || return 1
[[ "$(cat "$function_root/p_srate" 2>/dev/null || true)" == "48000" ]] || return 1
[[ "$(cat "$function_root/c_srate" 2>/dev/null || true)" == "48000" ]] || return 1
[[ "$(cat "$function_root/p_ssize" 2>/dev/null || true)" == "2" ]] || return 1
[[ "$(cat "$function_root/c_ssize" 2>/dev/null || true)" == "2" ]] || return 1
[[ "$(cat "$function_root/c_sync" 2>/dev/null || true)" == "adaptive" ]]
}
udc_state() {
local udc=""
udc=$(ls /sys/class/udc 2>/dev/null | head -n1 || true)
@ -1547,13 +1574,17 @@ LIVE_UVC_DESCRIPTOR_MISMATCH=0
if [[ "$HOST_GADGET_PROTECTED" == "1" ]] && uvc_gadget_present && ! live_uvc_descriptor_matches_request; then
LIVE_UVC_DESCRIPTOR_MISMATCH=1
fi
LIVE_UAC_DESCRIPTOR_MISMATCH=0
if [[ "$HOST_GADGET_PROTECTED" == "1" ]] && ! live_uac_descriptor_matches_request; then
LIVE_UAC_DESCRIPTOR_MISMATCH=1
fi
LIVE_UVC_FUNCTION_MISSING=0
if [[ -z ${LESAVKA_DISABLE_UVC:-} ]] && [[ "$HOST_GADGET_PROTECTED" == "1" ]] && ! uvc_gadget_present; then
LIVE_UVC_FUNCTION_MISSING=1
fi
ATTACHED_UVC_CHANGE_DEFERRED=0
if [[ "$HOST_GADGET_PROTECTED" == "1" ]] \
&& { [[ "$LIVE_UVC_DESCRIPTOR_MISMATCH" == "1" ]] || [[ "$LIVE_UVC_FUNCTION_MISSING" == "1" ]]; } \
&& { [[ "$LIVE_UVC_DESCRIPTOR_MISMATCH" == "1" ]] || [[ "$LIVE_UAC_DESCRIPTOR_MISMATCH" == "1" ]] || [[ "$LIVE_UVC_FUNCTION_MISSING" == "1" ]]; } \
&& { [[ "$EXPLICIT_GADGET_REBUILD" != "1" ]] || [[ -z ${LESAVKA_ALLOW_GADGET_RESET:-} ]]; }; then
ATTACHED_UVC_CHANGE_DEFERRED=1
fi
@ -1561,12 +1592,13 @@ ATTACHED_UVC_RESTART_DEFERRED=0
if [[ "$HOST_GADGET_PROTECTED" == "1" ]] \
&& [[ "$UVC_ENV_CHANGED" == "1" ]] \
&& [[ "$LIVE_UVC_DESCRIPTOR_MISMATCH" != "1" ]] \
&& [[ "$LIVE_UAC_DESCRIPTOR_MISMATCH" != "1" ]] \
&& [[ "$LIVE_UVC_FUNCTION_MISSING" != "1" ]] \
&& { [[ "$EXPLICIT_GADGET_REBUILD" != "1" ]] || [[ -z ${LESAVKA_ALLOW_GADGET_RESET:-} ]]; }; then
ATTACHED_UVC_RESTART_DEFERRED=1
fi
if [[ "$ATTACHED_UVC_CHANGE_DEFERRED" == "1" ]]; then
echo "⚠️ UVC runtime settings or live descriptors differ while the host is attached." >&2
echo "⚠️ UVC/UAC runtime settings or live descriptors differ while the host is attached." >&2
echo " The installer will not restart lesavka-core or lesavka-uvc because that can wedge the Pi USB controller." >&2
echo " To apply descriptor-changing UVC settings, use a maintenance window with LESAVKA_ALLOW_GADGET_RESET=1 LESAVKA_FORCE_GADGET_REBUILD=1." >&2
if lesavka_server_has_active_clients && [[ "${LESAVKA_INSTALL_RESTART_WITH_CLIENTS:-0}" != "1" ]]; then
@ -1672,6 +1704,11 @@ if [[ "$LIVE_UVC_DESCRIPTOR_MISMATCH" == "1" ]] && [[ "$HOST_GADGET_PROTECTED" =
GADGET_REBUILD_REASON="live UVC descriptor does not match requested codec ${INSTALL_UVC_CODEC}"
echo "⚠️ live UVC descriptor does not match requested codec ${INSTALL_UVC_CODEC}; forcing a gadget rebuild so descriptors and runtime agree."
fi
if [[ "$LIVE_UAC_DESCRIPTOR_MISMATCH" == "1" ]] && [[ "$HOST_GADGET_PROTECTED" == "1" ]]; then
FORCE_GADGET_REBUILD=1
GADGET_REBUILD_REASON="live UAC descriptor does not match requested host mixer/default audio settings"
echo "⚠️ live UAC descriptor does not match requested host mixer/default audio settings; forcing a gadget rebuild so descriptors and runtime agree."
fi
if [[ -n ${LESAVKA_FORCE_GADGET_REBUILD:-} ]]; then
FORCE_GADGET_REBUILD=1
EXPLICIT_GADGET_REBUILD=1

View File

@ -295,6 +295,22 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
SERVER_INSTALL.contains("LIVE_UVC_DESCRIPTOR_MISMATCH"),
"installer should catch partial previous runs where env already changed but live descriptors did not"
);
assert!(
SERVER_INSTALL.contains("live_uac_descriptor_matches_request")
&& SERVER_INSTALL.contains("LIVE_UAC_DESCRIPTOR_MISMATCH")
&& SERVER_INSTALL.contains("p_volume_present")
&& SERVER_INSTALL.contains("c_volume_present")
&& SERVER_INSTALL.contains("LESAVKA_UAC_HOST_MIXER_CONTROLS:-0"),
"installer should catch live UAC descriptor drift, including stale host mixer controls"
);
assert!(
SERVER_INSTALL.contains(
"UVC/UAC runtime settings or live descriptors differ while the host is attached"
) && SERVER_INSTALL.contains(
"live UAC descriptor does not match requested host mixer/default audio settings"
),
"installer should explain when UAC descriptor drift requires a maintenance-window gadget rebuild"
);
assert!(
SERVER_INSTALL.contains("LIVE_UVC_FUNCTION_MISSING"),
"installer should not rebuild a missing attached UVC function without explicit maintenance-window force"