実装手順の概略
実装するには?
HSPでUSBドライバが作れるのかどうかわかりませんが、作れたとしてもめんどくさいのでドライバの開発はやりません。
対象とするUSBデバイスは、USBドライバがすでにインストールされているものを対象とします。
基本的な面倒な処理のすべてはドライバにやってもらうことにします。
では、どうするかというとhid.dllを使います。(hid.dllの解説はよく分からないので省略。)
hid.dllのAPIを使えばドライバを介してUSBデバイスにアクセスできるようです。
hid.dllはWindowsに最初から入っているので特別なインストールの必要はありません。便利ですね。
資料は?
API使うので関数の詳細はMSDNです。
HIDのAPI関数のマニュアルは日本語化されていないので、英語版のMSDNを調べる必要があります。
[MSDN(HIDのAPI関数のマニュアル)]
https://msdn.microsoft.com/en-us/library/ff538865.aspx
私はほとんど英語が読めないのでInfoseekマルチ翻訳などの自動翻訳してくれるサイトを使ってます。
それでもうまく訳せない部分は自分で調べる必要があります。
HID以外のAPIも使用しますが、こちらは日本語訳されていますので日本語版MSDNを参照。
日本語版MSDN
http://msdn.microsoft.com/ja-jp/library/default.aspx
準備
もう少し前置きやらなにやら必要な気もしますが、すっとばしてさっそく使うための準備。
とりあえず、操作したいUSBデバイスのVendorIDとProductIDを調べます。
- 操作したいUSBデバイスをPCに接続します。
- 適切なUSBドライバをインストールして、USB機器が正常に動くことを確認します。
- 次に、操作したいUSBデバイスをソフトが見分けるために必要なVendorIDとProductIDを調べます。
- デバイスマネージャを開きます。
- ツリーから該当するデバイスのプロパティを開きます。
- 詳細タブのプロパティの項目をハードウェアIDにします。
- 値のリストに
-----
HID\VID_0000&PID_0000
-----
と書いてあると思います。赤で示した4桁の16進数で書かれた値がVendorIDとProductIDです。
「VID_」の後の4桁の数字がVendorID、「PID_」の後の4桁の数字がProductID。
この2つの値をメモしておきます。
これで準備完了です。
手順
目的のUSBデバイスへのパスを取得すればあとはWriteFileとReadFileでUSBデバイスへの送受信が可能になります。
しかし、このパスを得るまでに非常にめんどくさい儀式めいた作業が必要になります。
ざっくり流れを書いておきます。
- HidD_GetHidGuid関数でGUID(HIDの識別子)を取得する。
- SetupDiGetClassDevs関数でHIDクラスのデバイスリストへのハンドルを取得する。
↓こんなイメージになってるらしいです。HIDクラス ├ USBデバイス(0) ├ USBデバイス(1) ├ USBデバイス(2) ├ … └ USBデバイス(n)
- SetupDiEnumDeviceInterfaces関数で、 デバイスリストの先頭から順番にHIDクラスデバイスの情報を取得する。
- SetupDiGetDeviceInterfaceDetail関数で、 Windows内部でのデバイス名を取得する。デバイスにアクセスするためのパスなどを含んでいるようです。
- CreateFile関数で、リストから取り出したデバイスを開いて、そのデバイスハンドルを取得する。
USBデバイスをファイルと同じように扱えるようです。 - HidD_GetAttributes関数で、開いたデバイスの属性(所属・種類)を調べる。
ここで選んだデバイスのVendorIDとProductIDが出てきます。 - VendorIDとProductIDが操作したいUSBデバイスのIDかどうか調べる。
ここで、探しているデバイスでなければ3.に戻ってリストの次のデバイスを調べる。 - HidD_GetPreparsedData関数とHidP_GetCaps関数で
HIDデバイスの能力を取得し、パイプのデータサイズなどを取得します。
(パイプが複数あるデバイスの場合どうなるんでしょうね?その数の分だけCreateFileすればいいんでしょうか?) - ReadFile関数やWriteFile関数でデバイスの信号を受け取ったり、デバイスに振動を送ったりします。
途中、CloseHandle関数でデバイスハンドルを閉じたりといった作業もありますが、その辺は省略しました。
全体的な流れとしては、目的のUSBデバイスのデバイスハンドルが取得できれば、あとはReadFile/WriteFile/DeviceIoControlで通信。
という感じらしいです。
送受信内容も基本的な部分はドライバ任せになるらしく、パケットとかなんとかは特に気にしないでいいようです。
逆を言えば細かいことが出来ないわけですが…。(本当か?)
もっと詳細なデータ通信がやりたい場合は、VC++でドライバ作るか、libusb、WinUSBといった
ものに手を出す必要があります。
そこまでやると大変そうなのでここではやりません。エンドユーザーが別途インストール作業をする必要も出てきてしまいますからね。