Files
chromebox_10th_audio_driver/audio_topology/collected/collect_shell_audio.sh

367 lines
13 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# Chromebox 10 代 - 音频硬件拓扑收集脚本(跨平台版)
# 可自动检测运行环境ChromeOS 或 Linux
#
# 用于 C1a/C1c 任务:在 Linux 或 ChromeOS 下收集音频硬件拓扑信息
#
# 用法: ./collect_audio_topology.sh [输出文件]
# 默认输出到: audio_topology/collected/audio_topology_${ENV}_$(hostname)_$(date).txt
# 其中 ENV 为 chromeos 或 linux
#
# 建议:
# - 在 Linux 下用 sudo 运行以获取完整 dmesg/journalctl
# - 在 ChromeOS 下直接运行即可
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTPUT_DIR="${SCRIPT_DIR}/collected"
mkdir -p "$OUTPUT_DIR"
# ============================================
# 环境检测
# ============================================
detect_environment() {
# 检测是否为 ChromeOS
if [ -f /etc/lsb-release ] && grep -q "Chrome OS" /etc/lsb-release 2>/dev/null; then
echo "chromeos"
elif [ -f /etc/os-release ] && grep -q "cros" /etc/os-release 2>/dev/null; then
echo "chromeos"
elif [ -d /mnt/stateful_partition ] || [ -d /home/chronos ]; then
# ChromeOS 特有的目录
echo "chromeos"
else
echo "linux"
fi
}
ENV_TYPE=$(detect_environment)
echo "检测到运行环境: $ENV_TYPE"
# 根据环境生成输出文件名
if [ "$ENV_TYPE" = "chromeos" ]; then
OUTPUT="${1:-${OUTPUT_DIR}/audio_topology_chromeos_$(hostname)_$(date +%Y%m%d_%H%M%S).txt}"
else
OUTPUT="${1:-${OUTPUT_DIR}/audio_topology_linux_$(hostname)_$(date +%Y%m%d_%H%M%S).txt}"
fi
TMP_DIR=$(mktemp -d)
trap "rm -rf $TMP_DIR" EXIT
log() {
echo "[$(date +%H:%M:%S)] $*"
}
section() {
echo "" >> "$OUTPUT"
echo "========================================" >> "$OUTPUT"
echo "### $1" >> "$OUTPUT"
echo "========================================" >> "$OUTPUT"
echo "" >> "$OUTPUT"
}
run_cmd() {
local desc="$1"
shift
echo "# $desc" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
if "$@" >> "$OUTPUT" 2>&1; then
true
else
echo "(命令返回非零,可能部分信息缺失)" >> "$OUTPUT"
fi
echo "\`\`\`" >> "$OUTPUT"
echo "" >> "$OUTPUT"
}
# 带超时的命令执行(防止某些命令卡住)
run_cmd_timeout() {
local timeout_sec="$1"
local desc="$2"
shift 2
echo "# $desc" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
if timeout "$timeout_sec" "$@" >> "$OUTPUT" 2>&1; then
true
else
echo "(命令执行超时或失败)" >> "$OUTPUT"
fi
echo "\`\`\`" >> "$OUTPUT"
echo "" >> "$OUTPUT"
}
log "开始收集音频硬件拓扑..."
log "运行环境: $ENV_TYPE"
log "输出文件: $OUTPUT"
: > "$OUTPUT"
echo "# Chromebox 10 代 - 音频硬件拓扑" >> "$OUTPUT"
echo "# 运行环境: $ENV_TYPE" >> "$OUTPUT"
echo "# 收集时间: $(date -Iseconds)" >> "$OUTPUT"
echo "# 主机: $(hostname)" >> "$OUTPUT"
echo "" >> "$OUTPUT"
# --- 系统信息 ---
section "系统信息"
run_cmd "uname -a" uname -a
run_cmd "内核版本" uname -r
if [ -f /etc/lsb-release ]; then
run_cmd "Release (ChromeOS)" cat /etc/lsb-release
elif [ -f /etc/os-release ]; then
run_cmd "Release (Linux)" cat /etc/os-release | grep -E "^(NAME|VERSION)="
fi
run_cmd "CPU 信息" cat /proc/cpuinfo | grep -E "model name|processor" | head -10
run_cmd "内存信息" cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable"
# --- PCI 音频设备 ---
section "PCI 音频相关设备"
if command -v lspci &>/dev/null; then
run_cmd "lspci -nn | grep -i audio (含设备 ID)" bash -c "lspci -nn | grep -i audio || echo '(无匹配)'"
run_cmd "lspci -v -s $(lspci | grep -i audio | cut -d' ' -f1 | head -1)" bash -c "lspci -v -s $(lspci | grep -i audio | head -1 | cut -d' ' -f1) 2>/dev/null || true"
else
echo "# lspci 不可用" >> "$OUTPUT"
fi
# --- 播放/录音设备列表 ---
section "ALSA 设备列表"
if command -v aplay &>/dev/null; then
run_cmd "aplay -l (播放设备)" aplay -l
run_cmd "aplay -L (ALSA 设备描述)" aplay -L 2>/dev/null | head -30 || true
else
echo "# aplay 未安装" >> "$OUTPUT"
fi
if command -v arecord &>/dev/null; then
run_cmd "arecord -l (录音设备)" arecord -l
fi
run_cmd "cat /proc/asound/cards" cat /proc/asound/cards 2>/dev/null || true
run_cmd "cat /proc/asound/pcm (PCM 设备明细)" cat /proc/asound/pcm 2>/dev/null || true
# --- /proc/asound 目录结构 ---
section "/proc/asound 目录结构"
run_cmd "ls -la /proc/asound" ls -la /proc/asound 2>/dev/null || true
for card_dir in /proc/asound/card[0-9]*; do
if [ -d "$card_dir" ]; then
card=$(basename "$card_dir")
echo "# $card 目录内容:" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
ls -la "$card_dir" 2>/dev/null >> "$OUTPUT" || true
echo "\`\`\`" >> "$OUTPUT"
fi
done
# --- Codec 信息 (HDA) ---
section "HDA Codec 信息"
for codec in /proc/asound/card*/codec*; do
if [ -f "$codec" ]; then
echo "# $codec" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
cat "$codec" >> "$OUTPUT" 2>/dev/null || echo "(无法读取)" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
fi
done
# --- HDMI ELD 内容 ---
section "HDMI ELD 内容"
for eld in /proc/asound/card*/eld*; do
if [ -f "$eld" ]; then
echo "# $eld" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
cat "$eld" >> "$OUTPUT" 2>/dev/null || echo "(无法读取,或 ELD 为空/未连接)" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
fi
done
# --- /sys/class/sound 设备 ---
section "/sys/class/sound 设备"
if [ -d /sys/class/sound ]; then
run_cmd "ls -la /sys/class/sound" ls -la /sys/class/sound
for card in /sys/class/sound/card[0-9]*; do
if [ -d "$card" ]; then
echo "# $card 设备属性:" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
for f in id number; do
[ -f "$card/$f" ] && echo "$f: $(cat "$card/$f" 2>/dev/null)" >> "$OUTPUT"
done
echo "\`\`\`" >> "$OUTPUT"
fi
done
fi
# ============================================
# 平台相关收集(根据环境执行不同的命令)
# ============================================
if [ "$ENV_TYPE" = "chromeos" ]; then
# ========== ChromeOS 特有信息 ==========
# --- SOF 固件和拓扑信息 ---
section "SOF Firmware and Topology"
run_cmd "SOF firmware directory" ls -la /lib/firmware/intel/sof/ 2>/dev/null || echo "# SOF firmware directory not found" >> "$OUTPUT"
run_cmd "SOF topology directory" ls -la /lib/firmware/intel/sof-tplg/ 2>/dev/null || echo "# SOF topology directory not found" >> "$OUTPUT"
# --- CRAS 音频服务器信息 ---
section "CRAS Audio Server"
if command -v cras_test_client &>/dev/null; then
run_cmd "CRAS server info" cras_test_client --dump_server_info 2>/dev/null || echo "# cras_test_client --dump_server_info failed" >> "$OUTPUT"
run_cmd "CRAS audio thread info" cras_test_client --dump_a 2>/dev/null || true
fi
# --- PCI 设备详细信息 ---
section "PCI Audio Device Details"
if [ -d /sys/bus/pci/devices/0000:00:1f.3 ]; then
for f in class device vendor subsystem_device subsystem_vendor irq; do
[ -f "/sys/bus/pci/devices/0000:00:1f.3/$f" ] && echo "$f: $(cat /sys/bus/pci/devices/0000:00:1f.3/$f 2>/dev/null)" >> "$OUTPUT"
done
run_cmd "PCI audio driver" ls -la /sys/bus/pci/devices/0000:00:1f.3/driver 2>/dev/null || true
fi
# --- /dev/snd 设备 ---
section "/dev/snd devices"
run_cmd "ls -la /dev/snd" ls -la /dev/snd 2>/dev/null || echo "# /dev/snd not found" >> "$OUTPUT"
else
# ========== Linux 特有信息 ==========
# --- 内核日志 ---
section "内核日志 (dmesg) 音频相关"
echo "# dmesg | grep -iE 'snd|hda|audio|codec|hdmi'" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
if dmesg 2>/dev/null | grep -iE 'snd|hda|audio|codec|hdmi' >> "$OUTPUT"; then
true
else
echo "(需要 root 权限,请用 sudo 重新运行)" >> "$OUTPUT"
fi
echo "\`\`\`" >> "$OUTPUT"
# --- journalctl 内核日志 ---
if command -v journalctl &>/dev/null; then
section "journalctl 内核日志 (SOF/音频)"
echo "# journalctl -b -k --no-pager | grep -iE 'sof|snd|hda|audio|hdmi' | tail -80" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
if journalctl -b -k --no-pager 2>/dev/null | grep -iE 'sof|snd|hda|audio|hdmi' | tail -80 >> "$OUTPUT"; then
true
else
echo "(journalctl 需 root 权限)" >> "$OUTPUT"
fi
echo "\`\`\`" >> "$OUTPUT"
fi
# --- ACPI NHLT 表 ---
section "ACPI NHLT 表"
if [ -d /sys/firmware/acpi/tables ]; then
echo "# ls /sys/firmware/acpi/tables/ | grep -i nhlt" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
ls /sys/firmware/acpi/tables/ 2>/dev/null | grep -i nhlt >> "$OUTPUT" || echo "(未找到 NHLT 表)" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
fi
# --- sof-logger ---
section "sof-logger (可选)"
if command -v sof-logger &>/dev/null; then
echo "# sof-logger -t 2>/dev/null | tail -30" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
SOF_LOG=$(timeout 3 sof-logger -t 2>/dev/null | tail -30) || true
if [ -z "$SOF_LOG" ]; then
echo "(sof-logger 执行超时或需 root 权限)" >> "$OUTPUT"
else
echo "$SOF_LOG" >> "$OUTPUT"
fi
echo "\`\`\`" >> "$OUTPUT"
fi
# --- 音频服务 (PulseAudio/PipeWire) ---
section "音频服务 (PulseAudio / PipeWire)"
RUN_PACTL() {
if [ -n "${SUDO_USER:-}" ] && [ -d "/run/user/$(id -u "$SUDO_USER" 2>/dev/null)" ]; then
runuser -u "$SUDO_USER" -- env XDG_RUNTIME_DIR="/run/user/$(id -u "$SUDO_USER")" "$@"
else
"$@"
fi
}
if command -v pactl &>/dev/null; then
run_cmd "pactl info" RUN_PACTL pactl info 2>/dev/null || true
run_cmd "pactl list cards" RUN_PACTL pactl list cards 2>/dev/null | grep -E "Name:|device.description|active profile" >> "$OUTPUT" 2>/dev/null || true
run_cmd "pactl list sinks" RUN_PACTL pactl list sinks 2>/dev/null | grep -E "Name:|device.description|State" | head -30 >> "$OUTPUT" 2>/dev/null || true
fi
fi
# ========== 通用信息(两个平台都收集) ==========
# --- 音频相关内核模块 ---
section "音频相关内核模块"
run_cmd "lsmod | grep -iE 'snd|hda|sound'" bash -c "lsmod | grep -iE 'snd|hda|sound' || echo '(无匹配)'"
# --- ALSA 混音器状态 ---
section "ALSA 混音器状态"
if command -v amixer &>/dev/null; then
run_cmd_timeout 5 "amixer -c 0 contents (关键控件)" amixer -c 0 contents 2>/dev/null | grep -E "numid=|name=|values=" | head -100 >> "$OUTPUT" || true
fi
# --- SOF 固件信息 ---
section "SOF 固件 (Intel Sound Open Firmware)"
if [ -d /lib/firmware/intel ]; then
echo "# /lib/firmware/intel/ 中的 SOF 相关文件:" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
ls -la /lib/firmware/intel/ 2>/dev/null | grep -E 'sof|avs' >> "$OUTPUT" || echo "(未找到 SOF 固件)" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
for tplg_dir in /lib/firmware/intel/sof-tplg /lib/firmware/intel/sof; do
if [ -d "$tplg_dir" ]; then
echo "# 拓扑文件 ($tplg_dir):" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
ls -la "$tplg_dir/" 2>/dev/null | grep -E '\.tplg' | head -30 >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
fi
done
fi
# --- 主板信息 ---
section "主板/机型信息"
if [ -d /sys/class/dmi/id ]; then
echo "# DMI 信息:" >> "$OUTPUT"
echo "\`\`\`" >> "$OUTPUT"
for f in board_name product_name sys_vendor bios_version; do
[ -f "/sys/class/dmi/id/$f" ] && echo "$f: $(cat /sys/class/dmi/id/$f 2>/dev/null)" >> "$OUTPUT"
done
echo "\`\`\`" >> "$OUTPUT"
fi
# --- 收集信息摘要 ---
section "收集信息摘要"
echo "脚本: $0" >> "$OUTPUT"
echo "脚本目录: $SCRIPT_DIR" >> "$OUTPUT"
echo "运行环境: $ENV_TYPE" >> "$OUTPUT"
echo "输出文件: $OUTPUT" >> "$OUTPUT"
echo "文件大小: $(du -h "$OUTPUT" 2>/dev/null | cut -f1)" >> "$OUTPUT"
echo "行数: $(wc -l < "$OUTPUT" 2>/dev/null)" >> "$OUTPUT"
# ============================================
# 平台特定的下一步提示
# ============================================
section "下一步操作提示"
if [ "$ENV_TYPE" = "chromeos" ]; then
echo "1. 如需更完整的信息,请打开 chrome://system" >> "$OUTPUT"
echo "2. 找到 'audio' 部分并点击 'Expand'" >> "$OUTPUT"
echo "3. 将展开的内容复制粘贴到文件末尾" >> "$OUTPUT"
echo "" >> "$OUTPUT"
echo "--- 请在此处粘贴 chrome://system 的 AUDIO 部分 ---" >> "$OUTPUT"
else
echo "1. 如需更完整的 dmesg 信息,请用 sudo 重新运行此脚本" >> "$OUTPUT"
echo "2. 检查 PulseAudio/WirePlumber 服务状态systemctl --user status pipewire" >> "$OUTPUT"
echo "3. 测试 HDMI 音频speaker-test -D hw:0,3 -c 2 -t wav" >> "$OUTPUT"
fi
log "收集完成!"
log "运行环境: $ENV_TYPE"
log "输出文件: $OUTPUT"
log ""
log "文件命名规则已明确标识运行环境:"
if [ "$ENV_TYPE" = "chromeos" ]; then
log " - 文件名包含 'chromeos'"
log " - 文件头部有 '# 运行环境: chromeos'"
else
log " - 文件名包含 'linux'"
log " - 文件头部有 '# 运行环境: linux'"
fi