Raspberry piを使ってUSBデバイスサーバを作る(USB/IP)
はじめに
USB/IP(universal serial bus extension over IP network)を使って無料(ライセンス料無し)で複数個のUSBデバイスをネットワーク共有する手法についての記事です。
環境
- server : Raspbian GUN/Linux 10, Raspberry Pi 3 Model B
- client : Ubuntu 18.04.05 LTS
TL;DR
Raspberry piのUSB端子に接続したデバイスの通信を有線LANを介することで、ネットワーク上の他のPCに接続したかのように振舞わせることができます。
やりたいことのイメージ
USB over Ethernetを実現します。
Raspberry piでUSBデバイスサーバを立てます。
Raspberry piにUSBメモリなどのデバイスを接続し、その情報のやり取りを他のPCとの間で有線LAN経由で行います。
USB/IPとは
USB/IPとは、USBデバイスをIPネットワーク上で共有しようというプロジェクトの成果物です。
2007年ごろにNAISTで開発されたものであり、Linux 2.6.38でカーネルにマージされました。
USB/IP プロジェクトは IP ネットワーク上で汎用の USB デバイス共有システムを開発することを目的としている。コンピュータ間で USB デバイスを共有するために、USB/IP は "USB I/O メッセージ" を TCP/IP ペイロードにカプセル化してコンピュータ間で通信する。
ArchWiki
類似の手法など
類似の手法としては、VirtualHere、製品としては、IO-DATA社のnet.USBなどがあります。
- VirtualHere ソフトウェア。同時使用できる数は無料版では1デバイスまで。追加でネットワークに接続するには1デバイスにつき約$50のライセンス料を払わないと複数個のデバイスを共有できない。セットアップは非常に簡単なので共有するデバイスが1つだけの場合はこちらの方でも良い。linux対応。
- net.USB ネットワーク共有するための製品。linux非対応。
というわけで今回は、linux対応かつお金のかからないオープンな技術でトライしてみます。
セットアップ
初回のみ実行する必要があります。
Raspberry piでのserverのセットアップ
Raspberry piで行うべき設定。
Raspberry pi側の設定はIPの固定をします。
「raspberry pi ip 固定」などで検索すれば解説が多数あるので省略。
続いて、usbipをaptでインストールしておきます。
$ sudo apt install usbip
Ubuntu18.04でのclientのセットアップ
Ubuntuで行うべき設定。
USB/IPは予め3240番のポートを開放しておく必要があります。ufwを使ってポート開放を行います。
$ sudo ufw allow 3240/tcp
$ sudo ufw enable
$ sudo ufw reload
USP/IPはlinux-tools-genericというパッケージ内にあるのでaptを使ってインストールします。
$ sudo apt install hwdata linux-tools-generic
使い方
デバイスを接続するにはserver(Raspberry pi)でbindしてからclient(Ubuntu)でattachします。
取り外すにはclientでdetachしてからserverでunbindします。
???の部分は環境によって異なる。(ex.1-1.2)というように記述されていそうな例を示しています。
用語の説明
bind : server側で共有できるようにすること。serverから見たとき、bindするとデバイスが切り離されたように見える。
attach : 共有可能な状態になっている(bindされている)デバイスをclient側でマウントすること。
detach : attachしたデバイスをアンマウントすること。detachするデバイスはportを確認し、portを指定して行う(やり方は後述)。
server(Raspberry pi側)で普段使うコマンド
以下にRaspberry pi側で実行が必要なコマンドを示します。
今回、Raspberry piのIPアドレスは192.168.0.111に固定しています。
bind
server(Raspberry pi)側で共有できるようにします。serverから見たとき、bindすることでデバイスが切断されたように見えます。
$ sudo modprobe usbip_host
$ usbip list -l
カーネルモジュールのloadと、bindしたいデバイスのbusid(ここでは?????
)を調べます。
$ sudo usbip bind -b ?????
$ sudo usbipd -D
busidを指定してbindします。次に、デーモンを起動します。
unbind
clientでdetach(詳細は後述)してからbindを解除します。
$ sudo usbip unbind -b ?????
server(Raspberry pi側)で普段使うコマンドおわり。
client(PC側)で普段使うコマンド
以下にUbuntu(PC)側で実行が必要なコマンドを示します。
attach
共有可能な状態になっている(bindされている)デバイスをclient側でマウントします。
$ sudo modprobe vhci-hcd
$ /usr/lib/linux-tools/$(uname -r)/usbip list -r 192.168.0.111
ここで、192.168.0.111
は各自任意に設定したRaspberry piのIPアドレスです。適宜置き換えてください。
カーネルモジュールのloadと、bindしたいデバイスのbusid(=?????
)を調べます。
pathの$(uname -r)はtab補完で入力できます。
$ sudo /usr/lib/linux-tools/$(uname -r)/usbip attach -r 192.168.0.111 -b ?????(ex.1-1.2)
detach
attachしたデバイスをアンマウントします。detachするデバイスはportを確認し、portを指定して行います。
$ /usr/lib/linux-tools/$(uname -r)/usbip port
detachしたいデバイスのport(??
)を調べます。
$ sudo /usr/lib/linux-tools/$(uname -r)/usbip detach -p ??
portを指定してdetachを行います。
client(PC側)で普段使うコマンドおわり。
余談
最後のコマンドについて、/usr/lib..../usbipまでの部分はlnコマンドで省略すると使いやすいかもしれません。
Discussion