135 lines
3.5 KiB
Bash
Executable File
135 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# When VERIFY fails: PCI reset (root) + doctor --fix (desktop user), then re-verify.
|
|
# Run as your desktop user (same as kaisa-audio-doctor.sh). Reset step needs:
|
|
# sudo -n /path/to/reset-sof-hdmi-pci.sh
|
|
# (configure NOPASSWD for that absolute path).
|
|
#
|
|
# Typical:
|
|
# ./scripts/kaisa-audio-hdmi-watchdog.sh
|
|
# ./scripts/kaisa-audio-hdmi-watchdog.sh --loop --interval 300
|
|
#
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
RESET_SCRIPT="${KAISA_RESET_SCRIPT:-${REPO_ROOT}/scripts/reset-sof-hdmi-pci.sh}"
|
|
DOCTOR="${REPO_ROOT}/scripts/kaisa-audio-doctor.sh"
|
|
LOG_DIR="${KAISA_LOG_DIR:-${REPO_ROOT}/_logs}"
|
|
|
|
CONNECTED_ARGS=(--only-connected)
|
|
LOOPS=1
|
|
INTERVAL_SEC="${KAISA_WATCHDOG_INTERVAL:-120}"
|
|
LOOP_FOREVER=0
|
|
|
|
log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*"; }
|
|
|
|
usage() {
|
|
sed -n '1,40p' "$0" | sed -n '/^# /s/^# //p'
|
|
cat <<EOF
|
|
Options:
|
|
--loop Repeat until interrupted (sleep --interval between cycles)
|
|
--loops N Run N cycles (default: 1)
|
|
--interval SEC Sleep between cycles in --loop mode (default: ${INTERVAL_SEC})
|
|
--all-hdmi Do not pass --only-connected (verify/fix may probe pcm2/3/4; riskier)
|
|
-h, --help This help
|
|
EOF
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--loop) LOOP_FOREVER=1; shift ;;
|
|
--loops)
|
|
LOOPS="${2:?}"
|
|
shift 2
|
|
;;
|
|
--interval)
|
|
INTERVAL_SEC="${2:?}"
|
|
shift 2
|
|
;;
|
|
--all-hdmi) CONNECTED_ARGS=(); shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*)
|
|
echo "Unknown option: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if ! [[ "${LOOPS}" =~ ^[0-9]+$ ]] || [[ "${LOOPS}" -lt 1 ]]; then
|
|
echo "ERROR: --loops must be a positive integer" >&2
|
|
exit 2
|
|
fi
|
|
|
|
if [[ "${EUID}" -eq 0 ]]; then
|
|
echo "ERROR: run as desktop user, not root (doctor --fix needs user session)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -x "${DOCTOR}" ]]; then
|
|
echo "ERROR: missing doctor: ${DOCTOR}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "${RESET_SCRIPT}" ]]; then
|
|
echo "ERROR: missing reset script: ${RESET_SCRIPT}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
|
|
run_one_cycle() {
|
|
local cycle="${1:?}"
|
|
local ts
|
|
ts="$(date +%Y%m%d_%H%M%S)"
|
|
local v1 f1 v2
|
|
v1="${LOG_DIR}/kaisa-watchdog_${ts}_c${cycle}_verify.log"
|
|
f1="${LOG_DIR}/kaisa-watchdog_${ts}_c${cycle}_fix.log"
|
|
v2="${LOG_DIR}/kaisa-watchdog_${ts}_c${cycle}_reverify.log"
|
|
|
|
log "cycle ${cycle}: verify -> ${v1}"
|
|
if "${DOCTOR}" --verify "${CONNECTED_ARGS[@]}" --verify-strict -o "${v1}"; then
|
|
log "cycle ${cycle}: verify OK"
|
|
return 0
|
|
fi
|
|
|
|
log "cycle ${cycle}: verify FAILED -> sudo -n reset (${RESET_SCRIPT})"
|
|
if ! sudo -n "${RESET_SCRIPT}"; then
|
|
log "ERROR: sudo -n reset failed (password / NOPASSWD path?)"
|
|
return 1
|
|
fi
|
|
|
|
log "cycle ${cycle}: doctor --fix -> ${f1}"
|
|
"${DOCTOR}" --fix "${CONNECTED_ARGS[@]}" -o "${f1}" || true
|
|
|
|
log "cycle ${cycle}: re-verify -> ${v2}"
|
|
if "${DOCTOR}" --verify "${CONNECTED_ARGS[@]}" --verify-strict -o "${v2}"; then
|
|
log "cycle ${cycle}: re-verify OK after reset+fix"
|
|
return 0
|
|
fi
|
|
log "cycle ${cycle}: re-verify still FAILED (see ${v2})"
|
|
return 1
|
|
}
|
|
|
|
cycle=0
|
|
while true; do
|
|
cycle=$((cycle + 1))
|
|
if run_one_cycle "${cycle}"; then
|
|
:
|
|
else
|
|
log "cycle ${cycle}: recovery did not achieve clean verify"
|
|
fi
|
|
|
|
if [[ "${LOOP_FOREVER}" -eq 0 ]]; then
|
|
if [[ "${cycle}" -ge "${LOOPS}" ]]; then
|
|
break
|
|
fi
|
|
fi
|
|
|
|
if [[ "${LOOP_FOREVER}" -eq 1 ]] || [[ "${cycle}" -lt "${LOOPS}" ]]; then
|
|
log "sleep ${INTERVAL_SEC}s before next cycle"
|
|
sleep "${INTERVAL_SEC}"
|
|
fi
|
|
done
|
|
|
|
log "watchdog finished (${cycle} cycle(s))"
|