diff --git a/audio_topology/collected/collect_shell_audio.sh b/audio_topology/collected/collect_shell_audio.sh new file mode 100644 index 0000000000..7af4c7e74a --- /dev/null +++ b/audio_topology/collected/collect_shell_audio.sh @@ -0,0 +1,367 @@ +#!/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 \ No newline at end of file