WinUSBデバイスとシリアル通信するには

WinUSB

WindowsRuntimeでは、サードパーティー製のドライバで接続されたデバイスとのシリアル通信が禁止されています。

基本的にWindowsストアアプリなどからUSBデバイスとシリアル通信を行うには、USBデバイスが「WinUSB.sys」というドライバで認識されていなければいけません。

たとえばエレコムのUC-SGTなどは、RS232C→USBの変換ケーブルですが、公式でWinUSBをインストールするドライバパッケージ(中身はinfファイル)が提供されているのでドライバを入れれば、UC-SGTで接続されたデバイスはWindowsストアアプリからシリアル通信が可能となります。

とにかく、WindowsRuntimeでシリアル通信を行うには、デバイスをWinUSBというドライバで認識できなければ使うことができません。

 

デバイスをWinUSBとして認識させる2つの方法

デバイスをWinUSBとして認識させるには2つの方法があります。

  1. カスタムinfファイルを作成する方法 (条件 端末に物理キーボードが付いている場合)
  2. レジストリにGUIDを登録する方法 (条件 レジストリをいじっても問題無い場合)

 

1番目のカスタムinfファイルを作成する方法は、端末に物理キーボードが付いていることが条件になります。

なぜなら、オリジナルなinfファイルをつくり、インストールするためデジタル証明の無いドライバーをインストールする許可を端末に与えなければいけません。

Windows8.1でデジタル証明のないドライバをインストールする許可を与えるには、PCの設定→保守と管理→回復→PCの起動をカスタマイズする→トラブルシューティング→詳細オプション→その他の修復オプションを表示→スタートアップ設定に行き、

「7キー」を押してドライバー署名の強制を無効にするを押さなければいけません。

20140923_072229394_iOS

 

 

しかし端末に物理キーボードなどがついていない場合、7キーを押すことができません。USBキーボードを接続しても認識しない場合が多いので、ラップトップなど、PCに物理キーボードが標準で付いている場合はこちらのカスタムinfファイルを作成する方法をとれますが、端末に物理キーボードがついていない場合、レジストリをいじる必要があります。

 

2番目のレジストリにGUIDを登録する方法は、端末に物理キーボードがついていない場合使用します。

そもそもすべてのデバイスはデバイスマネージャからWinUSBドライバをドライバとして選択すればドライバを適用できます。

しかし、認識するときにシステムが登録されているGUIDにデバイスと一致するものがあるかどうか見に行くのですがその時にデバイスのGUIDがなくて認識できません。

そこで、レジストリにデバイスのGUIDを登録することでデバイスを認識することができます。

GUIDとはGlobally Unique Identifierの略でなにかを一意に決定する識別子(ID)です。

このような形をしています。{d53fa365-5ag4-4436-938b-9db4734c6ca3}

 

Arduinoを接続してみる

Arduinoマイコンとは様々IOが標準で搭載されたAVRマイコンで非常に使い勝手がよく、シリアル通信をすることもできます。

今回はArduino UNOを接続してみたいと思います。

20140923_114511201_iOS

 

カスタムinfファイルを作成する方法

こちらの方法でデバイスが認識できればGUIDを追加する方法はしなくてもよいです。

infファイルとは、Windowsのソフトウエアをインストール用の設定が記述されたファイルのことです。

事前にOSにinfファイルをインストールしておくと、デバイスが接続されたときそのinfファイルを仲介してWinUSBドライバを読み込んでくれます。

40

カスタムinfファイルとは、そのinfファイルを自分で記述して事前にインストールしておくことを指します。

 

ではカスタムinfファイルを作成してみましょう。

以下のテキストデータをテキストエディタで書き込みます。

編集すべきところは

%DeviceName% = と [Dev_AddReg] と ManufacturerName= と DeviceName= の4つです。

 

%DeviceName% =

ここではVendorIDとProductIDを指定します。

ArduinoのVendorIDとProductIDの取得方法は、通常の方法でArduinoのドライバーをインストールしてデバイスマネージャからプロパティを表示します。

41

 

ハードウエアIDの項目を見るとVID_****とPID_****が書かれています。

 

42

 

コレをさきほどの%DeviceName% =USB_Install, USB\以降に書きます。

おそらく同じArduinoUNOを使っているとVIDとPIDは同じ値になるはずです。

[Dev_AddReg]

ここではオリジナルのGUIDを作成して書き込みます。

GUIDの作成は、VisualStudioのGUID作成ツールで行います。

VisualStudioのメニューバーの[ツール]→[GUIDの作成]を押します。

43

 

GUID形式はレジストリ形式を選択し、[新規GUIDの作成]をしてコピーします。

44

 

GUIDをコピーしたら

[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,”*************”

の「*」の部分に貼り付けます。

 

ManufacturerName=

個々にはデバイスドライバの製造者名を書き込みます。なんでも大丈夫です

DeviceName=

個々には表示されるデバイス名を書き込みます。

ここに書いた値がデバイスマネージャに表示されます。

 

ここまでできたら拡張子を.infとしてファイルを保存しておきましょう。

45

 

デジタル署名の無いinfファイルのインストールを許可する

設定チャーム→PCの設定→保守と管理→回復→PCの起動をカスタマイズするで[今すぐ再起動をする]を押します。

そして青い画面で、トラブルシューティング→詳細オプション→その他の修復オプションを表示→スタートアップ設定に行き、

「7キー」を押します。

これでデジタル署名の無いinfファイルのインストールが許可されます。

 カスタムinfファイルをインストールする

では先ほど作成したinfファイルを右クリックして[インストール]を押しましょう。

49

 

[このドライバーソフトウエアをインストールします]をクリックします。

53

 

このダイアログが出れば成功です。

54

 

Arduinoの標準ドライバをアンインストールする。

カスタムinfファイルをインストールできたら現在インストールしている標準のArduinoドライバをアンインストールしましょう。

デバイスマネージャからArduinoUNOを削除します。

46

 

このデバイス・ドライバーソフトウエアを削除するにチェックをいれ、OKを押します。

47

 

できたら一度、Arduinoを抜き差ししましょう。

デバイスマネージャのユニバーサル・シリアル・バスデバイスの項目に自分がinfファイルに設定した名前と同じ名前でArduinoが認識できていれば成功です。

55

もし認識できていない場合は、不明なデバイスのどれかがArduinoなので、プロパティからVendorIDとProductIDで特定しましょう。

特定できたら、ドライバーソフトウエアの更新を押します。

57

 

コンピュータを参照してドライバーソフトウエアを検索します。を押します。

58

 

コンピュータ上のデバイス・ドライバーの一覧から選択します。を押します。

 

59

 

ユニバーサルシリアルバスデバイスを選択し、次へを押します。

 

60

 

正しくinfファイルがインストールされていればこの中の項目に自分の作成したinfファイルと同一名のものがあるのでそれを選択し、次へを押します。

62

 

 

ドライバーのインストールが完了すれば成功です。

64

カスタムinfファイルを作成する方法は以上で終わりです。

あとはWinUSBのAPIを利用することでシリアル通信が可能となります。

WinUSBのインストール

 

レジストリにGUIDを追加する方法

こちらの方法でデバイスが認識できればカスタムinfの方法はしなくても大丈夫です。

こちらの方法はレジストリを編集するので注意して編集してください。

もしレジストリを編集してお使いのPCの動作が不安定になっても私は責任を負いません。

 

レジストリにGUIDを追加する方法は、一度ArduinoをWinUSBドライバで読み込ませます。

現在インストールしているArduinoのドライバを一度削除します。

46

 

このデバイスのドライバーソフトウエアを削除するにチェックを入れ、[OK]を押します。

 

47

 

できたら一度、ハードウエアの変更のスキャンを押しましょう。

 

48

 

続いて[ほかのデバイス]の中から不明なデバイスのどれか1つがArduinoなのでプロパティを見てVendorIDとProductIDで特定しましょう。

特定できたらドライバーソフトウエアの更新を押します。

57

 

コンピュータを参照してドライバーソフトウエアを検索します。を押します。

58

コンピュータ上のデバイス・ドライバーの一覧から選択します。を押します。

59

ユニバーサルシリアルバスデバイスを選択し、次へを押します。

60

Microsoftの中に、WinUSBデバイスがあるのでそれを選択します。

61

ドライバーのインストールが完了すれば成功です。

63

 

GUIDを生成する

VisualStudioのGUID生成ツールを使ってGUIDを作りましょう。

VisualStudioのメニューバーの[ツール]→[GUIDの作成]を押します。

43

 

GUID形式はレジストリ形式を選択し、[新規GUIDの作成]をしてコピーします。

44

 

ではレジストリを編集します。

ファイル名を指定して実行で「regedit」と入力し、レジストリエディタを立ち上げます。

65

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\<VID_****&PID_*****>の下の更に下の改装にDevice Parametersがあるので、その中に新規で文字列を追加しましょう。

↑(****はArduinoのVendorIDとProductIDに対応)

 

名前は[DeviceInterfaceGUIDs]で値に先ほど作成したGUIDを設定します。

68

 

以上でGUIDを追加する方法は完了です。

あとはWinUSBのAPIから呼び出すとシリアル通信をすることができます。

 

USBシリアル通信の準備

では実際にUSBで接続されたデバイスとシリアル通信を行ってみましょう。

 

まずはPackage.manifestファイルを編集します。

Package.manifestファイルを右クリック→[コードの表示]を押しましょう。

37

Packageタグにwc属性を追加しましょう。

Capabilityタグの要素に以下を追加します。

wc:DeviceタグのId属性はVendorIDとProductIDを接続したいデバイスに置き換えてください。

m2:FunctionタグのType属性に関してはCDCコントロールは02 * *で共通です。

詳しくはWindowsデベロッパーセンターに載っています。

 

続いて以下のUsbSerialPortクラスをコピペして新しいクラスとして追加しましょう。

Usbシリアル通信はUsbDeviceクラスからUsbInterfaceクラスでインターフェースを指定してDataWriterとDataReaderで通信を行いますが、結構めんどくさいので以下のクラスを使ってシリアル通信をします。

 

USBSerialPortクラスを使う

では先ほどのUsbSerialPortクラスを使ってみましょう。

UsbDeviceクラスのGetDeviceSelectorメソッドにVendorIdとProductIdを指定してselectorを取得します。

その後、DeviceInformationのFindAllAsyncメソッドを使ってデバイスを取得します。

取得したDeviceのIdを使って、UsbDeviceを取得します。

そしてUsbDeviceを使ってUsbSerialPortクラスを初期化します。

 

UsbSerialPortを初期化したらOpenAsyncでポートをオープンします。

通信速度は9600とします。

 

データを受信した時のイベントをハンドルしておきます。

データのリッスンを開始します。

引数で指定したバイト数だけ読み込みます。

もしデータが流れてきた場合ListenDataReceivedイベントが発動します。

 

データを書き込みます。

今回は2という数字をバイトデータとして送ります。

 

Arduino側のプログラム

Arduinoはドライバを変更してしまったので別のPCでArduinoIDEを使ってプログラムを書き込む必要があります。

Arduino側のプログラムはシリアルポートにデータが流れてきたらそのままデータを返して13番のLEDを100ミリ秒点灯させます。

20140923_164841269_iOS

これでArduinoとタブレットをつないでプログラムを実行するとシリアル通信できます。