概要
- USBデバイスドライバ作成は思ったより難しくない
- Android端末のBootloaderモードを例に解説
- lsusbやlibusbを使ったデバイス情報取得方法
- ユーザ空間アプリでUSB制御が可能
- GET_STATUSやGET_DESCRIPTORリクエストによるデータ取得手順
USBデバイスドライバ入門
- USBデバイス のドライバ作成は一見難しそうだが、 Kernelコード を書く必要はない場合が多い
- ユーザ空間アプリケーション でUSB通信が可能、Socketsを使うのと似た感覚
- ハードウェアの専門知識がなくても、 libusb 等のライブラリを使えば簡単に扱える
- 参考資料として「 USB in a NutShell」などがあるが、初心者には難解な場合も
BootloaderモードのAndroid端末を例に
- 実験用デバイスとして AndroidスマートフォンのBootloaderモード を利用
- 入手が容易
- プロトコルがシンプルかつドキュメントも豊富
- OSに標準ドライバがなく、独自ドライバの開発がしやすい
- Bootloaderモードへの移行方法は機種ごとに異なるが、 特定のボタンを押しながら起動 するのが一般的
USBデバイスの手動列挙(Enumeration)
- 列挙(Enumeration)とは、 ホストがデバイスの情報を取得 するプロセス
- lsusb コマンドでデバイス情報を確認可能
- 例:
lsusb出力のID 18d1:4ee0は Vendor ID(VID): 18d1、 Product ID(PID): 4ee0 - VID はUSB-IFが企業に割り当て、 PID は企業が製品ごとに割り当て
- 例:
lsusb -tで デバイスツリー とクラス・ドライバ情報を表示- Class=Vendor Specific Class はメーカー独自プロトコル
- Driver=[none] ならOSがドライバを割り当てていない状態
Windowsの場合の注意
- Windowsでは lsusb が使えないため、 デバイスマネージャ や USB Device Tree Viewer 等で情報取得
- VID/PID が主な識別情報
- libusb を使えばユーザ空間でUSBデバイスにアクセス可能
- Windowsでは Winusb.sys ドライバが必要な場合もあり、 Zadig ツールでドライバ置換が可能
libusbによるデバイス列挙
- libusb を使い、 ホットプラグイベント でデバイス検出が可能
- 指定した VID/PID のデバイスが接続されたときにコールバック実行
- サンプルコードで libusb_hotplug_register_callback を利用
- デバイス接続時に「 Device plugged in!」と表示
- カーネルコード不要で、 ユーザ空間のみで検出・制御 が可能
デバイスとの通信:Control Endpoint
- 最初の通信は Control Endpoint(ID 0x00) 経由で行う
- OSもこのエンドポイントを使い、 VID/PID などを取得
- libusb_control_transfer 関数で GET_STATUS リクエストを送信
- 例:デバイスが 自己電源 か、 Remote Wakeup 対応かを取得
- 取得データの解釈はUSB仕様書を参照
ディスクリプタ(Descriptor)の取得
- ディスクリプタは デバイスの能力や情報を伝える構造体
- GET_DESCRIPTOR リクエストで取得
- 例:デバイスディスクリプタ(Device Descriptor)には bLength, bDescriptorType, idVendor, idProduct などが含まれる
- 他にも Configuration, Interface, Endpoint, String 等のディスクリプタが存在
- lsusb -v -d VID:PID で全ディスクリプタ情報を取得可能
まとめ
- USBデバイスドライバ作成は ユーザ空間アプリ でも十分対応可能
- libusb などのライブラリを使うことで、カーネルコード不要で デバイス検出・制御 ができる
- VID/PID や ディスクリプタ の取得・解析が基本的な流れ
- OSやデバイスによって必要なドライバや手順が異なるため、 環境ごとの注意 が必要