Tenho alguns rádios amadores que conecto ao meu computador Linux via USB. Os rádios se apresentam como placas de som, e ficam visíveis assim:
$ 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
Eles aparecem no USB como:
$ 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
O problema aqui é que tenho um software que quer conversar com um deles, mas não sabe qual. O software (js8call e wsjtx) simplesmente me permite selecionar o nome em um menu suspenso e lembrar o nome escolhido.
Os nomes neste menu suspenso são:
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
Outro software (por exemplo, direwolf) quer o dispositivo no formato "plughw:2,0", onde o outro rádio é "plughw:1,0".
Mas não é consistente qual é qual. Depende de quando o Linux os detectou, que na melhor das hipóteses é a ordem em que eu os conectei, e no caso normal é uma condição de corrida, já que ambos estão conectados e usando a mesma fonte de alimentação, então eles inicializam em ao mesmo tempo quando ligo a energia.
Então, como faço para o Linux nomear esses dois dispositivos de som de maneira consistente, para que eu não precise editar arquivos de configuração e alterar as configurações em uma interface do usuário, toda vez que eles forem detectados em uma ordem diferente?
Responder1
Os nomes no menu suspenso se parecem com os nomes das fontes do PulseAudio: consulte pacmd dump
. Eles incluiriam um número de série do dispositivo de som USB no descritor de dispositivo USB padrão (consulte Recursos lsusb -d 08bb:2901 -v | grep iSerial
). Se os rádios não tiverem nenhum identificador exclusivo detectável pelo Linux, pode ser complicado nomeá-los de forma consistente.
Os nomes do PulseAudio parecem ser gerados com base na ID_ID
propriedade, veja udevadm info -q property -p /sys/class/sound/card<N>
onde <N>
está o número do dispositivo de som em questão (a partir de card0
).
Você pode criar uma regra personalizada do udev que use, por exemplo, a ID_PATH
propriedade para identificar os rádios com base em qual porta USB física eles estão conectados e ajustar a ENV{ID_ID}
propriedade com base nisso para permitir que a interface de cada rádio seja identificada exclusivamente.
plughw:N,0
nomes são ALSA // .asoundrc
nomes /etc/alsa/conf.d
de dispositivos, consulte arecord -L
(notamaiúsculasEU). O N
número é igual ao atributo udev ATTR{number}
, visível com udevadm info -q all -a -p /sys/class/sound/card<N>
.
Você poderá usar nomes como plughw:CARD=<name>,DEV=0
se a versão do sistema operacional não for muito antiga. A <name>
parte é baseada no atributo udev ATTR{id}
, visível com udevadm info -q all -a -p /sys/class/sound/card<N>
.
Se você pode ou não modificar os atributos ATTR{number}
ou ATTR{id}
pelas regras do udev parece depender de qual versão do udev seu sistema possui: as versões mais recentes do udev parecem ser mais rigorosas que as mais antigas, ou talvez os sistemas mais novos tenham conjuntos de regras do udev mais complicados e eu simplesmente não não encontrei a maneira correta de configurá-los.
A ordem das regras do udev é importante: talvez você precise estudar as regras do udev existentes na sua distribuição Linux para descobrir se deve definir suas próprias regras para ativarantesoudepoisas regras padrão da distribuição para que suas regras realmente entrem em vigor. Distribuições antigas costumavam ter todas as regras do udev em um único diretório: as modernas possuem /etc/udev/rules.d/
customizações locais, enquanto as regras padrão do sistema estão localizadas em [/usr]/lib/udev/rules.d/
.
Com as distribuições modernas, se existir um arquivo de regras com o mesmo nome no /etc/udev/rules.d/
diretório de regras padrão do sistema e no diretório de regras padrão do sistema, o arquivo /etc/udev/rules.d/
substituirá o arquivo padrão correspondente, portanto, você nunca precisará modificar nenhum arquivo no diretório de regras padrão. . e assim você também nunca terá suas personalizações substituídas por atualizações de pacote.
Como uma solução alternativa para o ALSA, se você achar que não consegue modificar os atributos necessários do udev, você pode fazer com que o udev gere um /etc/alsa/conf.d/*.conf
arquivo para todo o sistema, que defina nomes de dispositivos ALSA personalizados adequados para seus rádios após identificá-los por algum atributo adequado do udev.
A documentação do ALSA tem um exemplo antigo de como atribuir números de dispositivos ALSA a dispositivos USB pela porta USB à qual estão conectados:
https://alsa.opensrc.org/Udev#A_working_example
É bastante complexo e requer a compilação de um pequeno programa para atuar como auxiliar do udev e foi projetado para lidar com saída de áudio em vez de dispositivos de entrada, mas deve ser um ponto de partida viável. Também inclui algumas funcionalidades que você não precisa, ou seja, configurar um dispositivo de saída combinado que inclua todos os dispositivos de som USB conectados.
Responder2
A solução mais fácil é substituir o id
atributo com base no caminho USB.
Parece que a solução simples é colocar isso em /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"
Pegue KERNELS
from udevadm info -ap /sys/class/sound/controlC2
, onde 2
está o índice da placa de áudio.
A resposta acima é a resposta curta e resolve-a para programas com um menu suspenso que expõe o ID.
Boas perguntas e respostas sobre estes outros tópicos:
- Mesmo nome de dispositivo para placas de som USB idênticas após cada reinicialização
- Regras do Udev para dispositivos aparentemente indistinguíveis
Embora isso não defina um número consistente de placa de som ALSA, torna óbvio qual é qual. Por 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
Se você quiser ir mais longe e obter uma numeração ALSA consistente, você pode criar um conjunto de links simbólicos. Por exemplo
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"
E tenha um script que verifique o caminho e retorne um nome adequado. Por exemplo
#!/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"
Você pode então criar um dispositivo PulseAudio consistente assim:
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