Linux上でのUSBデバイスのポート識別

categories: pc
tags: linux

課題

SonyのワンボードマイコンSpresenseと、衛星信号測位基板Allystar HD9310(旧基板)とでは、ともにUSB UARTドライバとしてSilicon Labs. CP210xを利用しています。Raspberry PiなどのLinux上では、両者とも/dev/ttyUSBx(xには数値が入ります)なるデバイスで認識されます。

この両者を接続した状態で再起動すると、/dev/ttyUSB0/dev/ttyUSB1の2つのデバイスが現れますが、タイミングによりどちらがSpresenseになるかわかりません。

多くの方々は、idVendoridProductとで自動識別されるようにudevという仕組みを設定されていますが、この両者はともに10c4ea60であり、そのままではSpresenseとHD9310とを区別ができません。この両者をLinux上で個別に認識する方法を考えました。

調査

例えば、Raspberry Piにより/dev/ttyUSB0として認識されたデバイスは何か、もう一方の/dev/ttyUSB1として認識されたデバイスは何か、そして、その両者の違いを観察します。そのために、次のようなコマンドを実行します。

udevadm info -a -n /dev/ttyUSB0

この結果を、例えばttyUSB0.txtなるファイルにリダイレクトし、/dev/ttyUSB1についても同様にファイルに保存して、diffコマンドなどにより両者の相違を探ります。あるいは、

udevadm monitor --environment --udev

を実行して、デバイスをUSBポートから抜き差ししてもよいでしょう。

私の使っているルールファイル

結局、私は次のようにしました。Spresenseを利用するためには/dev/ttyDCR(DCRとはdisaster and crisis management reportのことで、私はこのSpresenseをみちびきの災害・機器管理通報サービスの受信に用いています)にて、HD9310を利用するためには/dev/ttyHD9310にアクセスすればよく、便利です。

# u-blox ZED-F9P
KERNEL=="ttyACM*",\
    ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9",\
    SYMLINK+="ttyF9P"

# ES920LR
KERNEL=="ttyUSB*",\
    ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001",\
    SYMLINK+="ttyES920LR"

# Allystar HD9310
KERNEL=="ttyUSB*",\
    ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60",\
    ATTRS{product}=="CP2104*",\
    SYMLINK+="ttyHD9310"

# Sony Spresense
KERNEL=="ttyUSB*",\
    ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60",\
    ATTRS{product}=="CP2102N*",\
    SYMLINK+="ttyDCR"

# EOF

このルールファイルを/etc/udev/rules.d/00-spresense-hd9310.rulesなどのファイルに保存して、/etdc/udev/rules.d/ディレクトリにおき、次のコマンドを実行すると、自動的に、例えば、/dev/ttyUSB0などのデバイスファイルに/dev/ttyDCRなどのリンクが作成されます。

udevadm control --reload-rules && udevadm trigger

このルールファイルには、私のよく利用するu-blox ZED-F9Pのものや、EASEL ES920LRのものも記述しています。