複数のUSBサウンドカードが接続されているUSBポートで区別

複数のUSBサウンドカードが接続されているUSBポートで区別

私が望むのは、複数のUSBサウンドカードを一貫して区別し、接続されたUSBポートで識別し、この知識を使用してJavaプログラムの特定のサウンドカードでサウンドを再生できることです。

これまでは、USBポートを介してサウンドカードを識別する最初の部分にとどまっています。

私が最初にしたことは、以下のアドバイスに従うことでした。この問題Udevルールを使用してサウンドカードに名前を割り当てると、スクリプトは次のようになります。このウェブサイト

私が追加したUdevルールは次のとおりです。

KERNEL=="controlC[0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="hwC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="midiC[D0-9]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"
KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", NAME="snd/%c{1}"

内容は次のとおりですalsa_name.pl

use strict;
use warnings;
#
my $alsaname = $ARGV[0]; #udev called us with this argument (%k)
my $physdevpath = $ENV{PHYSDEVPATH}; #udev put this in our environment
my $alsanum = "cucu";
#you can find the physdevpath of a device with "udevinfo -a -p $(udevinfo -q path -n /dev/snd/pcmC0D0c)"
#
#
$physdevpath =~ s/.*\/([^\/]*)/$1/; #eliminate until last slash (/)
$physdevpath =~ s/([^:]*):.*/$1/; #eliminate from colon (:) to end_of_line
#
if($physdevpath eq "1-1.3.1")
{
       $alsanum="11";
}
if($physdevpath eq "1-1.3.2")
{
       $alsanum="12";
}
if($physdevpath eq "1-1.3.3")
{
       $alsanum="13";
}
if($physdevpath eq "1-1.3.4")
{
       $alsanum="14";
}

#
if($alsanum ne "cucu")
{
       $alsaname=~ s/(.*)C([0-9]+)(.*)/$1C$alsanum$3/;
}
#
print $alsaname;
exit 0;

これでUSBサウンドカードを接続してみると、/var/log/syslog完全に機能しないことがわかります。

NAME="snd/%c{1}" ignored, kernel device nodes cannot be renamed; please fix it in /etc/udev/rules.d/99-com.rules:16

以下に基づいてUdevルールを修正してみました。このリポジトリUdevルールを提供します。

SUBSYSTEM!="sound", GOTO="my_usb_audio_end"
ACTION!="add", GOTO="my_usb_audio_end"

DEVPATH=="/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/sound/card?", ATTR{id}="SPEAKER"
DEVPATH=="/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/sound/card?", ATTR{id}="HEADSET"

LABEL="my_usb_audio_end"

だから私は古いスクリプトを使ってルールを修正しました。

KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", ATTR{id}="snd/%c{1}

しかし、syslog今教えてください。

error opening ATTR{some_very_long_id} for writing: Permission denied

私も試しましたこの回答そしてそうだった

KERNEL=="pcmC[D0-9cp]*", DRIVERS=="usb", PROGRAM="/usr/bin/alsa_name.pl %k", SYMLINK+="snd/%c{1}

にエラーは表示されませんsyslog。大丈夫だと思いますが、再生デバイスを次のようにaplay -lリストすると

card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

どのUSBポートに接続しても何も変わりません。 Javaプログラムでも有用または区別可能な項目は表示されません。AudioSystem.getMixerInfo()

私のアプローチが正確で、いくつかの詳細がありませんか?それとも完全に間違った方向ですか?

ベストアンサー1

あなたは正しい道を行っています。 udevには問題が発生する可能性があるものがたくさんあります。 udevルールが機能しなくなった理由NAME="..."は、カーネルがこのようにデバイス名を変更することを許可していないためです。シンボリックリンクの生成は通常仕事に関連していますが、SYMLINK+=alsaがそれに興味があるかどうかはわかりません。

だから、おそらく正しい解決策はあなたに与えられた提案だと思います。リンクされた記事タイトルに2つの同じオーディオデバイスを識別する。ルールを使用してDEVPATH==デバイスを一致させ、またはで見つけることができるATTR{id}="ABC"一意の名前をデバイスに割り当てます。aplay -lcat /proc/asound/cards

まず、同じ作業を手動で試してください。 USBサウンドカードはなく、内蔵デバイスのみですので、次のようにしてください。

find /sys/devices/ -name id | grep sound

「id」という名前の多くの項目がリストされていますが、その一部はディレクトリであり、一意です。文書興味深いのは、このファイルを作成するとデバイス名(「PCH」)が保存されること/sys/devices/.../sound/card0/idですcat。この擬似ファイルに文字列を書き込むと名前が変更されます。

sudo sh -c 'printf "%s" MYCARD >/sys/devices/.../sound/card0/id'

これはの出力で見ることができますaplay -l。これがudevでやりたいことです。 sysfs擬似ファイルidは次のとおりです。プロパティcard0。したがって、udevはATTR{id}=一致が正しいディレクトリにある場合にのみ機能します。私の場合は/sysそうです。/sys/devices/.../sound/card0これがudevルールが言う理由ですDEVPATH=="/sys/devices/.../sound/card?"(カード番号は変更される可能性があるため、ワイルドカード「?」に置き換えられます)。

より完全な例については、ルールファイル全体を提供するリンクの上記のセクションを参照してください85-my-usb-audio.rules

おすすめ記事