159 lines
5.1 KiB
Bash
Executable File
159 lines
5.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Story C:清空 ring buffer 后试播 HDMI,再保存「仅本次」相关 dmesg(真机、Kaisa)
|
||
# 用法见:_bmad-output/stories-hdmi-kaisa-bp-2026-04-04.md — Story C 操作卡片
|
||
#
|
||
# sudo ./scripts/collect-storyc-dmesg.sh clear
|
||
# sudo ./scripts/collect-storyc-dmesg.sh save STOCK|PATCHED
|
||
#
|
||
# sudo ./scripts/collect-storyc-dmesg.sh auto STOCK|PATCHED [plughw:卡,设备]
|
||
# → dmesg -C → speaker-test → 保存 dmesg
|
||
# 设备优先级:第 3 参数 > 环境变量 STORYC_HDMI_PLUGHW(须 sudo -E 才继承)> aplay 检测首个 HDMI
|
||
# 推荐:sudo ./scripts/collect-storyc-dmesg.sh auto PATCHED plughw:0,3
|
||
#
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
COLLECTED="$REPO_ROOT/audio_topology/collected"
|
||
mkdir -p "$COLLECTED"
|
||
|
||
need_root() {
|
||
if [[ "${EUID:-}" -ne 0 ]]; then
|
||
echo "请使用 sudo 运行本脚本。" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 从 aplay -l 取第一个含 HDMI 的 playback 行,输出 plughw:卡,设备
|
||
detect_hdmi_plughw() {
|
||
local line
|
||
while IFS= read -r line; do
|
||
[[ "$line" =~ [Hh][Dd][Mm][Ii] ]] || continue
|
||
[[ "$line" =~ card[[:space:]]+([0-9]+):.*device[[:space:]]+([0-9]+): ]] || continue
|
||
echo "plughw:${BASH_REMATCH[1]},${BASH_REMATCH[2]}"
|
||
return 0
|
||
done < <(aplay -l 2>/dev/null)
|
||
return 1
|
||
}
|
||
|
||
write_snapshot() {
|
||
local label="$1"
|
||
local host kr ts out
|
||
host="$(hostname -s)"
|
||
kr="$(uname -r)"
|
||
ts="$(date +%Y%m%d_%H%M%S)"
|
||
out="$COLLECTED/dmesg_storyC_${label}_${kr}_${host}_${ts}.txt"
|
||
{
|
||
echo "# Story C — ${label}(仅本次 ring buffer 内自 clear 后的记录)"
|
||
echo "# 主机: $(hostname)"
|
||
echo "# 时间: $(date -R)"
|
||
echo "# 内核: $kr"
|
||
if [[ -n "${STORYC_AUTO_DEV:-}" ]]; then
|
||
echo "# auto: speaker-test 设备=${STORYC_AUTO_DEV} 退出码=${STORYC_AUTO_ST:-?}(124=timeout)"
|
||
fi
|
||
echo "#"
|
||
echo "### dpkg(镜像包)"
|
||
for p in "linux-image-${kr}" "linux-image-unsigned-${kr}"; do
|
||
dpkg -l "$p" 2>/dev/null || true
|
||
done
|
||
echo ""
|
||
if [[ -n "${STORYC_AUTO_LOG:-}" && -f "${STORYC_AUTO_LOG}" ]]; then
|
||
echo "### speaker-test 输出(stderr/stdout)"
|
||
cat "$STORYC_AUTO_LOG" || true
|
||
echo ""
|
||
fi
|
||
echo "### dmesg(过滤:SOF / HDMI / IPC)"
|
||
dmesg -T 2>/dev/null | grep -iE 'sof-audio|sof_intel|snd_sof|STREAM_PCM|ipc tx|pcm[0-9].*HDMI|HDMI[0-9]:|iDisp|0x60010000|0x80010000|error.*-5|ASoC error' || true
|
||
echo ""
|
||
echo "### dmesg(未过滤全文,ring 较短时即「仅本次」)"
|
||
dmesg -T 2>/dev/null
|
||
} >"$out"
|
||
[[ -n "${STORYC_AUTO_LOG:-}" && -f "${STORYC_AUTO_LOG}" ]] && rm -f "$STORYC_AUTO_LOG"
|
||
unset STORYC_AUTO_DEV STORYC_AUTO_ST STORYC_AUTO_LOG
|
||
echo "已写入: $out"
|
||
wc -l "$out"
|
||
}
|
||
|
||
run_auto() {
|
||
need_root
|
||
local lab="${1:?缺少标签 STOCK|PATCHED}"
|
||
local dev_cli="${2:-}"
|
||
case "$lab" in
|
||
STOCK|PATCHED) ;;
|
||
*)
|
||
echo "用法: sudo $0 auto STOCK|PATCHED [plughw:卡,设备]" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
command -v aplay >/dev/null 2>&1 || {
|
||
echo "未找到 aplay,请安装 alsa-utils。" >&2
|
||
exit 1
|
||
}
|
||
command -v speaker-test >/dev/null 2>&1 || {
|
||
echo "未找到 speaker-test,请安装 alsa-utils。" >&2
|
||
exit 1
|
||
}
|
||
local dev
|
||
if [[ -n "$dev_cli" ]]; then
|
||
dev="$dev_cli"
|
||
echo "使用命令行设备参数: $dev"
|
||
elif [[ -n "${STORYC_HDMI_PLUGHW:-}" ]]; then
|
||
dev="$STORYC_HDMI_PLUGHW"
|
||
echo "使用环境变量 STORYC_HDMI_PLUGHW: $dev(若未生效,请用第 3 参数或 sudo -E)"
|
||
else
|
||
dev="$(detect_hdmi_plughw)" || {
|
||
echo "aplay -l 中未找到 HDMI 设备。请指定:sudo $0 auto $lab plughw:卡,设备号" >&2
|
||
exit 1
|
||
}
|
||
echo "检测到 HDMI 设备: $dev(可用第 3 参数或 STORYC_HDMI_PLUGHW 覆盖)"
|
||
fi
|
||
STORYC_AUTO_LOG="$(mktemp)"
|
||
dmesg -C
|
||
echo "已 dmesg -C;开始 speaker-test(约 10s 超时)…"
|
||
set +e
|
||
timeout 10 speaker-test -c 2 -l 1 -D "$dev" </dev/null >"$STORYC_AUTO_LOG" 2>&1
|
||
STORYC_AUTO_ST=$?
|
||
set -e
|
||
STORYC_AUTO_DEV="$dev"
|
||
write_snapshot "$lab"
|
||
}
|
||
|
||
case "${1:-}" in
|
||
clear)
|
||
need_root
|
||
dmesg -C
|
||
echo "已执行 dmesg -C。请立即用 HDMI 试播一次,然后运行:"
|
||
echo " sudo $0 save STOCK"
|
||
echo "或: sudo $0 auto STOCK"
|
||
;;
|
||
save)
|
||
need_root
|
||
lab="${2:-STOCK}"
|
||
case "$lab" in
|
||
STOCK|PATCHED) ;;
|
||
*)
|
||
echo "第二个参数应为 STOCK 或 PATCHED,收到: $lab" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
write_snapshot "$lab"
|
||
;;
|
||
auto)
|
||
if [[ -z "${2:-}" ]]; then
|
||
echo "用法: sudo $0 auto STOCK|PATCHED(须显式指定,以免与当前内核状态不符)" >&2
|
||
exit 1
|
||
fi
|
||
run_auto "$2" "${3:-}"
|
||
;;
|
||
*)
|
||
echo "Story C:采集 dmesg(Kaisa / SOF HDMI)"
|
||
echo ""
|
||
echo " sudo $0 clear # 仅清空 ring,再手动试 HDMI,再 save"
|
||
echo " sudo $0 save STOCK|PATCHED # 保存当前 ring"
|
||
echo " sudo $0 auto STOCK|PATCHED [plughw:0,3] # clear → speaker-test → save"
|
||
echo ""
|
||
echo "指定 HDMI:优先「第 3 参数」;STORYC_HDMI_PLUGHW 需 sudo -E 才能传入子进程。"
|
||
exit 1
|
||
;;
|
||
esac
|