#!/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