WinUSB : USB ユーザーモードドライバ

Facebooktwittergoogle_plustumblrmail

以下、旧サイト (http://hpcgi1.nifty.com/~kokubu/index.cgi?WinUSB) から記事を移動してきました。内容は少々古くなっていますが、今でも参考程度にはなると思います。

Index

  • USE AT YOUR OWN RISK
  • 概要
  • 対象 OS
  • サポート機能
  • 開発環境の準備
    • ダウンロード
    • インストール
  • 作成したドライバのインストール方法
    • WinUSB co-installer DLL が必要
    • WDF co-installer DLL が必要
    • 適切な内容を記述した INF ファイルが必要
  • 注意点、落し穴など
    • WinUsb_QueryDeviceInformation() で DEVICE_SPEED を得る時の注意点
    • Vista パッチと WDF 1.7 co-installer とで発生するインストール不具合
  • 参考



USE AT YOUR OWN RISK

私はここに書いた内容を一切保証しませんので、試される方はくれぐれもご自身の責任下でおねがいします。困った時に自分だけで対処できないのなら、手をつけない事をお勧めします。

概要

以前から汎用 USB ドライバというコンセプト自体はあって、実際にそれを実装された uusbd.sys + uusbd.dll 等という例もありましたが、やっと MS もサポートする気になったのか、最近になって WinUSB という USB ドライバ機構が公開されました。

WinUSB も uusbd.* 同様、カーネルモードドライバ (winusb.sys) とそれを扱う為の API を公開しているユーザーモード DLL (winusb.dll) の二段構成となっています。アプリケーションを作る際には winusb.dll を使って通信処理を書けば良く、カーネルモードドライバを製作する手間は省略できるので、これからの USB ドライバ開発は大変楽になると思われます。

対象 OS

  • Windows 9x : 非対応
  • Windows 2000 : 非対応
  • Windows XP : SP2以降で対応
  • Windows Vista : 対応



サポート機能

コントロール転送
バルク転送
インタラプト転送
アイソクロナス転送不可
選択サスペンド
リモートウェイクアップ
複合デバイスへの応用可(※1)
ショートパケット送信Bulk-OUT Pipe を WinUSB_SetPipePolicy() で SHORT_PACKET_TERMINATE=TRUE と設定
ショートパケット受信Bulk-IN Pipe を WinUSB_SetPipePolicy() で IGNORE_SHORT_PACKETS=FALSE と設定
共有 I/O (デバイス 1 個への、複数プロセスからのアクセス)不可

 

※1 “How to Use WinUSB to Communicate with a USB Device” より :『 For multifunction devices, you can use the device’s INF to specify either an in-box kernel-mode driver or WinUsb.sys for each USB function separately. However, you can specify only one of these options for a particular function, not both.


開発環境の準備

ダウンロード

WinUSB を使ったドライバを作る為には WDK と WDF の 2 つが必要です。記事作成時点での最新は、 WDK が 6001.18001 、 WDF が 1.7 です。これらは残念ですが、 MSDN からはダウンロードできず、 Microsoft Connect から入手するしかありません (なんでだろう ?) 。

  • Microsoft Connect へ参加し、「 WDK / WLK / WDF Site 」を開く。
  • ダウンロードページから「 WDK for Server 2008 」を探してダウンロード。
  • ダウンロードページから「 WDF (KMDF and UMDF) 1_7 」を探してダウンロード。


インストール

ダウンロードしたファイルをインストールします。

  • 「 WDK for Server 2008 」をインストールする。一旦 DVD に焼く必要があるけども、それが嫌ならば ISO からファイルを抽出するツールを利用すれば OK 。
  • 「 WDF (KMDF and UMDF) 1_7 」をインストールする。
  • 「 WDF (KMDF and UMDF) 1_7 」のインストールによってできた WINDDKWDFREDIST1.7redistWDF を、「 WDK for Server 2008 」のインストール先の WINDDK6001.18001redistwdf へ、ディレクトリツリー毎コピーする (WDK をインストールした直後の WINDDK6001.18001redistwdf へ、ひとつだけ入っているテキストファイルの中に、この手順が書いてあるが、その意味を見切っていれば省略可能な手順だと思う) 。


作成したドライバのインストール方法

WinUSB ドライバのインストールは、普通のデバイスドライバのインストールと同様、関連ファイルを INF ファイルへ記述してインストールします。 WinUSB を利用したデバイスドライバで必要な関連ファイルを、以下に示します。

  1. WinUSB co-installer DLL
  2. WDF co-installer DLL
  3. 適切な内容を記述した INF ファイル


尚、マイクロソフトからは、 winusb.sys や winusb.dll のファイル単体配布はしていません。その代わり、 それらのファイルは WinUSB co-installer DLL の中に入っています。従がって、インストールが正しく完了した後ならば、システムにコピーされています。

余談ですが、 WinUSB のインストールには結構長い時間が掛かる様です。僕の環境では「分オーダー」、大体 3 分位掛かりました。気長に待ちましょう。

WinUSB co-installer DLL が必要

WinUSB 機構をシステムへ追加する為に co-installer が必要です。この co-installer は MS が配布している WDK に含まれています。 WDK をインストールしたディレクトリ WinDDKredistwinusb にある、以下のファイルを使えば OK です。

  • WinUSBCoInstaller.dll


WDF co-installer DLL が必要

WinUSB が WDF (正確には WDF の中の KMDF) に依存しているので、 WDF 機構をシステムへ追加する為に co-installer が必要です。この co-installer も MS が配布している WDK に含まれています。 WDK をインスールしたディレクトリ WinDDKredistwdf にある、以下のファイルを使えば OK です (見れば分かりますが、ファイル名の一部にバージョン番号を含んでいます) 。ファイルは CPU アーキテクチャに従がって複数存在しますので、適切な DLL がインストールされる様に INF を記述します (次節) 。

  • WDF version 1.5 を利用している場合は WdfCoInstaller01005.dll
  • WDF version 1.7 を利用している場合は WdfCoInstaller01007.dll


適切な内容を記述した INF ファイルが必要

“How to Use WinUSB to Communicate with a USB Device” を読めば詳しく書いてあるので簡単な説明だけに留めますが、 INF 記述にあたり必要となる要素には、以下の様なものがあります。

  • ClassGUID の為の GUID 値
  • DeviceInterfaceGUID の為の GUID 値
  • CatalogFile? があれば cat ファイル (64 ビット版 Windows では必須)
  • 対向相手となる USB デバイスの Vendor ID と Product ID
  • その他、いくつかの文字列要素


という事で、 “How to Use WinUSB to Communicate with a USB Device” でも紹介されている Fx2 デバイス向けのサンプル INF を例にします。


[Version]
Signature = "$Windows NT$"

### (1)
Class = MyDeviceClass

### (2)
ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}

Provider = %ProviderName%

### (3)
CatalogFile=MyCatFile.cat

; ========== Manufacturer/Models sections ===========

[Manufacturer]
%ProviderName% = MyDevice_WinUSB,NTx86,NTamd64

[MyDevice_WinUSB.NTx86]

### (4)
%USBMyDevice.DeviceDesc% =USB_Install, USBVID_0547&PID_1002

[MyDevice_WinUSB.NTamd64]

### (5)
%USBMyDevice.DeviceDesc% =USB_Install, USBVID_0547&PID_1002

; =================== Installation ===================

[USB_Install]
Include=winusb.inf
Needs=WINUSB.NT

[USB_Install.Services]
Include=winusb.inf
AddService=WinUSB,0x00000002,WinUSB_ServiceInstall

[WinUSB_ServiceInstall]
DisplayName = %WinUSB_SvcDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%WinUSB.sys

[USB_Install.Wdf]
KmdfService=WINUSB, WinUsb_Install

[WinUSB_Install]

### (6)
KmdfLibraryVersion=1.7

[USB_Install.HW]
AddReg=Dev_AddReg

[Dev_AddReg]

### (7)
HKR,,DeviceInterfaceGUIDs,0x10000,"{b35924d6-3e16-4a9e-9782-5524a4b79bac}"

[USB_Install.CoInstallers]
AddReg=CoInstallers_AddReg
CopyFiles=CoInstallers_CopyFiles

[CoInstallers_AddReg]

### (8)
HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01007.dll,WdfCoInstaller","WinUSBCoInstaller.dll"

[CoInstallers_CopyFiles]
WinUSBCoInstaller.dll

### (9)
WdfCoInstaller01007.dll

[DestinationDirs]
CoInstallers_CopyFiles=11

; ================= Source Media Section =====================

[SourceDisksNames]
1 = %DISK_NAME%,,,i386
2 = %DISK_NAME%,,,amd64

[SourceDisksFiles.x86]
WinUSBCoInstaller.dll=1

### (10)
WdfCoInstaller01007.dll=1

[SourceDisksFiles.NTamd64]
WinUSBCoInstaller.dll=2

### (11)
WdfCoInstaller01007.dll=2

; =================== Strings ===================

### (12)
[Strings]
ProviderName="MyWinUsbTest"
USBMyDevice.DeviceDesc="Test using WinUSB only"
WinUSB_SvcDesc="WinUSB Test"
DISK_NAME="My Install Disk"

 

  • (1) 自作したデバイスのクラスのクラス名を指定しています。ここに “USB” を指定してはいけません。
  • (2) 自作したデバイスのクラスを表わす GUID を指定します。 GUIDGEN.EXE 等を利用して作れば OK 。
  • (3) カタログファイルを持っていれば、ここに指定します。 64 ビット版 Windows では必須です。
  • (4) この行の最後で Vendor ID と Product ID を指定します。直前のセクション指定により、 x86 系アーキテクチャ用記述である事が分かります。
  • (5) 前述 (4) と同様に、この行の最後で Vendor ID と Product ID を指定します。但し、こちらは AMD 64 系アーキテクチャ用記述です。
  • (6) WDF (正確には KMDF) のバージョンを指定します。ここで指定したバージョンは、以降の (8) 、 (9) 、 (10) 、 (11) での WdfCoInstaller99999.dll のファイル名に含まれるバージョン番号と同期していないといけません。
  • (7) この行の最後で DeviceInterfaceGUID を指定します。 GUIDGEN.EXE 等を利用して作れば OK 。
  • (8) WdfCoInstaller99999.dll のバージョン番号部分を KmdfLibraryVersion? に合わせて修正します。その他はそのままで OK 。
  • (9) WdfCoInstaller99999.dll のバージョン番号部分を KmdfLibraryVersion? に合わせて修正します。
  • (10) WdfCoInstaller99999.dll のバージョン番号部分を KmdfLibraryVersion? に合わせて修正します。その他はそのままで OK 。
  • (11) WdfCoInstaller99999.dll のバージョン番号部分を KmdfLibraryVersion? に合わせて修正します。その他はそのままで OK 。
  • (12) これらへは、好きな文字列を定義すれば OK です。


注意点、落し穴など

WinUsb_QueryDeviceInformation() で DEVICE_SPEED を得る時の注意点

OHCI 、 UHCI 、 EHCI のホストチップが混在している環境下で WinUsb_QueryDeviceInformation() で DEVICE_SPEED を問い合わせした時、何が返って来るのか ? ドキュメントでは明確に説明されていません。 (僕の感覚は「未定義」と解釈しています。)

Vista パッチと WDF 1.7 co-installer とで発生するインストール不具合

「WinUSB.sys事始め」さんで触れられていましたが (http://winusb.at.webry.info/200806/article_2.html) 、 Vista では使用する co-installer に注意が必要だそうです。

ただ「 Windowsデバイスドライバ開発のためのヒント」さんによれば (http://www.devdrv.co.jp/windows/) 、問題が起こるのはバージョンが 6001.18000 の WDK であり、本稿で紹介している 6001.18001 では問題は修正済っぽいです。

以下、大本営発表 (http://www.microsoft.com/japan/whdc/driver/wdf/default.mspx) を引用 :

KMDF および UMDF 1.7 に関する重要なお知らせ

Windows Update から配布される 2 つの更新プログラム (938371 および 933607) により、Windows Vista において、カーネルモード ドライバーフレームワーク (KMDF) およびユーザーモード ドライバー フレームワーク (UMDF) のインストールで問題が生じる場合があることが判明しました。

この問題を修正するために、更新された WDF 1.7 co-installer がリリースされました。この件に関するアナウンスを参照し、 MSI パッケージをダウンロードするには、Microsoft Connect Web サイト (https://connect.microsoft.com/default.aspx) にアクセスしてください。サインイン後に、[会員制プログラム] の [Windows Driver Kit (WDK), Windows Logo Kit (WLK) and Windows Driver Framework (WDF)] をクリックします。

発表日: 2008 年 4 月 18 日 * 発表更新日: 2008 年 9 月 12 日



参考

Facebooktwittergoogle_plustumblrmail
Yusuke Dada K.
Yusuke Dada K.
台湾の現地企業で主に組み込みソフトウエアの研究開発をしている日本人です。我人是個日本人,負責軟體的研究開發。在臺灣的科技公司工作。

2件のコメント

  1. 貴重な情報をありがとうございます。
    64bit版のドライバーを作ろうとしております。
    WDKの7600.・・・srcumdffx2_driverfinalをbuildしてみましたら、amd64のフォルダーに、dllファイルが作られました。
    これも、インストールするのか、アプリケーションと同じフォルダーに置けば良いのかが分からない状況です。
    インストールは、DPInstを使用する予定です。
    hiken

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です