Usb

如何始終如一地命名音頻設備?

  • November 2, 2021

我有幾個業餘無線電,我通過 USB 連接到我的 Linux 電腦。收音機將自己顯示為音效卡,並且像這樣可見:

$ aplay -l
[...]
card 1: CODEC [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 1/1
 Subdevice #0: subdevice #0
card 2: CODEC_1 [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 1/1
 Subdevice #0: subdevice #0

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: CODEC [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 1/1
 Subdevice #0: subdevice #0
card 2: CODEC_1 [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 0/1
 Subdevice #0: subdevice #0

它們在 USB 上顯示為:

$ lsusb | grep Audio
$ lsusb | grep Aud
Bus 001 Device 102: ID 08bb:2901 Texas Instruments PCM2901 Audio Codec
Bus 001 Device 099: ID 08bb:2901 Texas Instruments PCM2901 Audio Codec

這裡的問題是我有軟體想與其中一個對話,但它不知道是哪一個。該軟體(js8call 和 wsjtx)只允許我從下拉列表中選擇名稱,並記住選擇的名稱。

此下拉列表中的名稱是:

alsa_input.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo
alsa_input.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo.2

其他軟體(例如 direwolf)希望設備採用“plughw:2,0”格式,而其他無線電為“plughw:1,0”。

但這並不一致。這取決於 Linux 何時檢測到它們,在最好的情況下是我插入它們的順序,在正常情況下,這是一個競爭條件,因為兩者都插入並使用相同的電源,所以它們在在我打開電源的同時。

那麼,如何讓 Linux 以一致的方式命名這兩個聲音設備,這樣我就不必在每次碰巧以不同的順序檢測到它們時編輯配置文件和更改 UI 中的設置?

id最簡單的解決方案是根據 USB 路徑覆蓋屬性。

似乎簡單的解決方案是將其放置在/etc/udev/rules.d/99-myrules.conf

SUBSYSTEM=="sound",KERNELS=="1-1.4.4:1.0",ATTR{id}="CODEC_7300"
SUBSYSTEM=="sound",KERNELS=="1-1.3.4:1.0",ATTR{id}="CODEC_9700"

KERNELSfrom udevadm info -ap /sys/class/sound/controlC22音效卡的索引在哪裡。

以上是簡短的答案,並為帶有公開 ID 的下拉列表的程序解決了這個問題。

關於這些其他執行緒的好問題和答案:

雖然這並沒有設置一致的 ALSA 音效卡編號,但它確實讓哪個是哪個音效卡很明顯。每aplay -l

**** List of PLAYBACK Hardware Devices ****
[...]
card 2: CODEC_7300 [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 1/1
 Subdevice #0: subdevice #0
card 3: CODEC_9700 [USB Audio CODEC], device 0: USB Audio [USB Audio]
 Subdevices: 1/1
 Subdevice #0: subdevice #0

如果您想更進一步並獲得一致的 ALSA 編號,您可以創建一組符號連結。例如

KERNEL=="controlC[0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.sh %k", SYMLINK+="%c"
KERNEL=="hwC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.sh %k", SYMLINK+="%c"
KERNEL=="midiC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.sh %k", SYMLINK+="%c"
KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.sh %k", SYMLINK+="%c"

並有一個檢查路徑並返回合適名稱的腳本。例如

#!/bin/bash
NAME="$1"
if echo "$DEVPATH" | grep 1-1.4; then
   NAME="$(echo "$NAME" | sed -r 's/(.*)C([0-9]+)(.*)/\1C11\3/')"
fi
if echo "$DEVPATH" | grep 1-1.3; then
   NAME="$(echo "$NAME" | sed -r 's/(.*)C([0-9]+)(.*)/\1C12\3/')"
fi
exec echo "snd/$NAME"

然後,您可以像這樣創建一致的 PulseAudio 設備:

N=11
DEV="radio-7300"
pacmd load-module module-alsa-card \
     device_id="${N}" name="${DEV}" \
     card_name="alsa_card.platform-${DEV}_audio" \
     namereg_fail=false tsched=no fixed_latency_range=no \
     ignore_dB=no deferred_volume=yes use_ucm=yes \
     card_properties="module-udev-detect.discovered=1"
pacmd suspend-sink alsa_output.${DEV}.analog-stereo no
pacmd suspend-source alsa_input.${DEV}.analog-stereo no

下拉列表中的名稱類似於 PulseAudio 源名稱:請參閱pacmd dump. 它們將包括一個 USB 聲音設備的序列號,在標準 USB 設備描述符中有一個(請參閱 參考資料lsusb -d 08bb:2901 -v | grep iSerial)。如果收音機沒有 Linux 可檢測到的唯一標識符,那麼要讓它們保持一致的命名可能會很棘手。

PulseAudio 名稱似乎是根據ID_ID屬性生成的,請查看相關聲音設備的編號udevadm info -q property -p /sys/class/sound/card<N>在哪裡<N>(從 開始card0)。

您也許可以創建一個自定義 udev 規則,該規則使案例如ID_PATH屬性來辨識無線電,基於它們插入的物理 USB 埠,並ENV{ID_ID}基於此調整屬性以允許唯一辨識每個無線電的介面。


plughw:N,0names are ALSA //.asoundrc設備/etc/alsa/conf.d名,見arecord -L(注意大寫L)。該N數字等於 udev 屬性ATTR{number},用 可見 udevadm info -q all -a -p /sys/class/sound/card<N>

plughw:CARD=<name>,DEV=0如果作業系統版本不是太舊,您也許可以使用類似的名稱。該<name>部分基於 udev 屬性ATTR{id},可見於udevadm info -q all -a -p /sys/class/sound/card<N>.

您是否可以通過 udev 規則修改ATTR{number}orATTR{id}屬性似乎取決於您的系統具有哪個版本的 udev:較新版本的 udev 似乎比舊版本更嚴格,或者可能較新的系統具有更複雜的 udev 規則集,而我只是沒有找不到設置它們的正確方法。

udev 規則的順序很重要:您可能需要研究 Linux 發行版的現有 udev 規則,以確定是否應該在發行版的標準規則之前之後設置自己的啟動規則,以使您的規則真正生效。舊發行版過去將所有 udev 規則放在一個目錄中:現代發行版/etc/udev/rules.d/用於本地自定義,而係統標準規則位於[/usr]/lib/udev/rules.d/.

/etc/udev/rules.d/在現代發行版中,如果系統標準規則目錄中和系統標準規則目錄中都存在同名規則文件,則該文件/etc/udev/rules.d/將覆蓋相應的標准文件,因此您永遠不需要修改標準規則目錄中的任何文件。 . 因此,您的自定義設置也不會被包更新覆蓋。

作為 ALSA 的替代解決方案,如果您發現無法修改所需的 udev 屬性,您可以讓 udev 為您生成一個系統範圍的/etc/alsa/conf.d/*.conf文件,該文件在通過一些合適的 udev 屬性辨識它們之後為您的無線電定義合適的自定義 ALSA 設備名稱。


ALSA 文件有一個關於如何通過它們連接到的 USB 埠將 ALSA 設備編號分配給 USB 設備的舊範例:

https ://alsa.opensrc.org/Udev#A_working_example

它相當複雜,需要編譯一個小程序來充當 udev 助手,並且旨在處理音頻輸出而不是輸入設備,但它應該是一個可行的起點。它還包括一些您不需要的功能,即設置包含所有插入式 USB 聲音設備的組合輸出設備。

引用自:https://unix.stackexchange.com/questions/675428