🍇

Raspberry PiとJetson Nano(2GB)のUSBポートのデバイスを物理的に抜き差しせず、ソフトウェアで制御する

2021/03/08に公開

毎度忘れるんで。

/sys/bus/usb/drivers/usb/bind/sys/bus/usb/drivers/usb/unbind にUSBポート名を流し込むことで、挿し(bind)抜き(unbind)をソフトウェアで制御できます。

bind/unbindに連動してudevのイベントが発火します。

各デバイスでの物理USBポートとOS上での識別名

Raspberry Pi 4 Model B

Raspberry Pi 4 Model B / USBポート

Raspberry Pi 3 Model B+

Raspberry Pi 3 Model B+ / USBポート

Raspberry Pi 3は有線LANポートがUSBで接続されているため、lsusbに表示されます。
1-1.1.1 を unbind すると eth0 が無くなりますよ。

Jetson Nano (2GB)

Jetson Nano (2GB) / USBポート

コマンド

1-1.2 を対象にした操作は以下の通りです。

挿し

$ echo -n "1-1.2" | sudo tee /sys/bus/usb/drivers/usb/bind

抜き

$ echo -n "1-1.2" | sudo tee /sys/bus/usb/drivers/usb/unbind

※ tee の仕様上、改行無しで "1-1.2" と表示されたりしますが、しょうがないっすね。

lsusbを使用したOS上での識別名の確認方法

Raspberry Pi 4 に対して、以下のように挿している場合のlsusbの結果は以下の通りです。

  • 1-1.2 = Wi-Fi アダプタ
  • 1-1.3 = USBドングル型モデム
  • 1-1.4 = USBメモリ
$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    |__ Port 1: Dev 25, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 2: Dev 28, If 0, Class=Vendor Specific Class, Driver=rtl8192cu, 480M
        |__ Port 3: Dev 33, If 0, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 1, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 2, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 3, Class=Vendor Specific Class, Driver=huawei_cdc_ncm, 480M
        |__ Port 4: Dev 31, If 0, Class=Mass Storage, Driver=usb-storage, 480M

USBドングル型アダプタのようなデバイスは複数のシリアルポートが存在しますが、1つのUSBポートに割り当てられることがありますが、操作としては1つのポートとなります。

この状態で 1-1.3 を unbind してみると以下のようになります。

$ echo -n "1-1.3" | sudo tee /sys/bus/usb/drivers/usb/unbind
1-1.3$ ## <ENTER> で整形
$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    |__ Port 1: Dev 25, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 2: Dev 28, If 0, Class=Vendor Specific Class, Driver=rtl8192cu, 480M
        |__ Port 4: Dev 31, If 0, Class=Mass Storage, Driver=usb-storage, 480M

この時点で udev も「デバイスが抜かれた」イベントが発生します。
sudo udevadm monitor でその様子が確認できます。

また 1-1.3 を bind (挿す) をしてみます。

$ echo -n "1-1.3" | sudo tee /sys/bus/usb/drivers/usb/bind
1-1.3$ ## <ENTER> で整形
$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    |__ Port 1: Dev 25, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 2: Dev 28, If 0, Class=Vendor Specific Class, Driver=rtl8192cu, 480M
        |__ Port 3: Dev 33, If 0, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 1, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 2, Class=Vendor Specific Class, Driver=option, 480M
        |__ Port 3: Dev 33, If 3, Class=Vendor Specific Class, Driver=huawei_cdc_ncm, 480M
        |__ Port 4: Dev 31, If 0, Class=Mass Storage, Driver=usb-storage, 480M

この時点で udev も「デバイスが挿された」イベントが発生します。

EoT

Discussion