Linuxのudevルールを使ってUSBデバイスを挿入する順番の制約を無くそう
USBデバイスの挿入順番で困るとき
USBデバイスがたくさんつながるLinuxで動く機器を作る人向けの記事です。ソフトよりの組み込み系エンジニアとかラズパイ(Raspberry Pi)で何か作ったりする人とかを想定しています。
Linuxは、USBデバイスをたくさんつなげると/dev/ttyACM0
, /dev/ttyACM1
, /dev/ttyACM2
... みたいな感じで対応するデバイス名が増えていきます。
このときソフトでdev/ttyACM0
とかデバイスを指定すると、USBの挿す順番によって動かなくなってしまうので困りますね。
自分もニンジャランタンという趣味ガジェットを作ったとき、諸事情によりSeeedさんのシリアルデバイスに対応する必要があったため、この問題にぶちあたりました。これに限らず昔からよくぶち当たってんたんですけど、仕事関係だったので対応方法とかわざわざネットに書いてなかったのです。
ニンジャランタン
Seeedさんのデバイス(Seeed Studio XIAO ESP32C3)
udevルールを使おう
解決方法は「udevルールを使う」です。これだけ覚えておけば、ネットで調べれば解決方法は色々でてきます。以下記事とか実践的で分かりやすいですね。
自分がラズパイで実際にやった例を書いておきます。Linux OSならIntel系でもラズパイ(Arm系)でも同じようにできます。
まずはlsusb
コマンドを使って、デバイスのIDを調べます。
最初にUSBデバイスを抜いた状態で実行します。
pi@raspberrypi:~/ninja-lantern $ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0853:013f Topre Corporation REALFORCE 108JP
Bus 001 Device 003: ID 056e:0054 Elecom Co., Ltd Black Grast Laser Mouse
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
次に、USBデバイスを挿入した状態で実行しましょう。
pi@raspberrypi:~/ninja-lantern $ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0853:013f Topre Corporation REALFORCE 108JP
Bus 001 Device 003: ID 056e:0054 Elecom Co., Ltd Black Grast Laser Mouse
Bus 001 Device 006: ID 303a:1001 Espressif USB JTAG/serial debug unit
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
差分となる以下が対象のUSBデバイスであることが分かります。
Bus 001 Device 006: ID 303a:1001 Espressif USB JTAG/serial debug unit
会社名を表すベンダーIDが303a
、製品名を表すプロダクトIDが1001
となります。
あとは/etc/udev/rules.d/
に99-seeed-serial.rules
といったudevルールのファイルを作成します。
今回の例だと、udevルールのファイルの中身は以下になります。
SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", SYMLINK+="seeedusbserial", MODE="0666"
SYMLINK+="seeedusbserial"
でデバイスファイル名を指定できます。MODE="0666"
は、指定すると書き込み権限が付与されるので、わざわざUSBデバイスに対して毎回chmod 666 /dev/xxx
と実行する必要がなくなります。
ファイルを作成した後、以下のコマンドを実行すると、設定が反映されます(再起動してもOKです)。
$ sudo udevadm control --reload
この状態で、USBデバイスを挿入すると/dev/seeedusbserial
というデバイスファイル名が追加されるようになります。
あとはソフトの方で/dev/seeedusbserial
を指定すればUSBデバイスの挿入順番を気にする必要はなくなります。便利ですね!
USBポートで固定
本記事ではとりあつかいませんが、udevルールを使ってUSBポートの場所で固定することもできます。興味ある方は調べてみてください。
まとめ
udevルールの使い方をまとめました。GitHubでソフト公開したりするときは、config
ディレクトリとかの下に.rules
ファイルを入れておいて、セットアップスクリプトでsudo cp config/xxx.rules /etc/udev/rules.d/
みたいな感じのコマンドを追加しておくと親切かなと思います。
以下はニンジャランタンのGitHubです。
udevルール追加の際のPRです。
他、有名どころですと例えばIntelのRealSenseとかもudevルールを使ったりしています。独自のカメラ系を複数使ったりする人は参考になるかなと思います。機種のバリエーションが多くてちょっと複雑ですが、configディレクトリ以下にudevルールズの設定ファイルがあります。
関連記事
Discussion