WindowsでMSD+CDC (USB Composite Device)
少し前に『USBでMSD+CDC (Composite Device)』という記事を書きましたが、実装がほぼ完了しました。ところがすんなりと行かないのがM$のWindows、というわけで色々と試行錯誤を行ってみました。その奮闘記をここに記しておこうと思います。
呪文のような文章が長々と続きますので、続きをどうぞ。
前回の記事ではMSD(Mass Strage Device)とCDC(Communication Device Class)を同時に実装する方法について考察をしました。要約すると問題点は、CDCは上位であるデバイスクラスで定義されるものであるのに対し、MSDは下位のインターフェイスで定義されるものであるため、定義のレベルが違う両者を両立させてComposite Deviceとする為にはどうすればよいのか、ということでした。結局解決方法としては、以下の2通りが存在します(それ以外のアングラな方法もあるようですが、それについては触れません)。
- CDCをデバイスクラスとしてMSDをその中に含める
- CDCとMSDをインターフェイスのレベルで定義し、CDCについてはInterface Association Descriptor(IAD)で補強をする
一見、1の方法がシンプルなように見えますが、OS側から見ると少し複雑な事情を解決しなければなりません。これは、OSから見たとき、デバイスクラスがCDCなのにも関わらず別の機能であるMSDが『いきなり』含まれるため、あらかじめOS側でCDC内に別の機能が存在するという心の準備ができていないといけないことに起因しています。
一方の2の方法ですが、これはあらかじめデバイスクラスにおいてbDeviceClass=FEh等で中身にIADが潜んでいるを教えているので、OS側から見れば解決は容易です。
実際Windowsにおいて1の方法では、このデバイスは一見CDC単体に見えるけど実はそうではなくてCompositeなんだよ、と教えるためのinf(CDCのinfとは異なる)を、ユーザが別途用意する必要があります。より具体的に述べると、composieデバイスを扱う親ドライバ(usbccgp.sys)をロードするためのusb.infへの参照、ならびに親ドライバ下位へCDCの定義を中継する宣言、が含まれたinfが必要となります。このあたりの話はM$の『Enumeration of the Composite Parent Device』、ならびにinfの例が記述された『Enumerating Interface Collections on Wireless Mobile Communication Devices』あたりが参考になります。親ドライバの詳細については、同じくM$の『USB Common Class Generic Parent Driver』をどうぞ。
また参考にあげたページからもわかるとおり、1の方法はVistaである必要があるようです。実際XP Professional(SP2)で上記のinfを用意した上で試してみましたが、CDCを構成する2つのInterface、すなわちCommunication ClassとData Interface Classが別々のデバイスとして認識されてしまい、うまく機能しませんでした。Windows XPの親ドライバは、『Windows での USB Interface Association Descriptor のサポート』内の『USBCCGP の変更点』を読む限りでは、親ドライバ下位にCDCの情報が伝達されるといった記述がないために失敗したのだと思います(詳細を述べるなら親ドライバがCDCのUnion Functional Descriptorを認識していないようです)。今後のService Packにおいて、Vistaと同じ仕様に変更されることを望みます。
方法2については、Windowsであっても親ドライバが自動的に読み込まれるので、MSDについては特に何もしなくても認識されます。その為にMSD内にCDCを認識させるためのinfをあらかじめ入れておけば、ドライバディスク代わりにデバイスを利用することが可能です。こちらについてXP Professional(SP2)で試したところ、予定どおりinfなしでMSDは認識されました。しかしながらCDCの認識については方法1と同様のトラブルが発生してしまい、2つのinterfaceが一つのCDCデバイスとして認識されませんでした(図1)。なお利用しているDescriptorはC言語で記述してあり、F34x_MSD_USB_Descriptor.c (F34x_MSD_USB_Descriptor.hならびにF34x_CDC.hも参照ください)のようになっています。
さらに調べてみると、M$のHotfix(正式リリースではないパッチ)にcompositeデバイスでのCDCの認識不良を取り扱ったものがありました。『The Usbser.sys driver may not load when a USB device uses an IAD to define a function that has multiple interfaces, and this function uses the Usbser.sys driver file in Windows XP』というものです。また親ドライバusbccgp.sysの不良を扱ったものとして『The network interface on a multifunction, composite USB device does not work in Windows XP』があります。現在これらのHotfixの入手ならびに適用を検討しています。結果がわかり次第、ここに掲載します。
※後日談
上記のHotfixを当ててみたが解決しない…と思っていたところ、ケアレスミスをしていることに気づき、それをなおした結果、快適に動作しています。そのミスとはIADのbDescriptorTypeを0x11としていたのですが、正しくは0x0Bでした。usb.orgにあるIADの文章には対応する数字が11と書いてあったので、これを16進表記と早合点したのが原因であったようです。上記のヘッダに対しても訂正を行っておきました。
Hotfixを当ててしまった後なので、果たしてHotfixを当てないと動かないかどうかについては検証していません。ということでSP2ならHotfixなしでも、動いてしまうかもしれません。
認識されるとデバイスマネージャは上のようになります。以前はデバイスが3つできていたので、その時点でIADの記述を疑うべきでした。
※※さらに後日談
認識されはしましたが、通信がうまくいっていません。ムキー!!
コメント
>たろさん
こんにちは。自分のinfファイルを見てみたのですが、[Model]という項目は見当たりませんが、複合デバイスにする際はMI(数字)を指定する必要があると思われます。
http://msdn.microsoft.com/en-us/library/aa476408.aspx
infは以下で公開しています。
https://fenrir.naruoka.org/download/autopilot/external/NAV2/inf/
またリンクを読み進めていただくとわかると思いますが、結局CDCとは異なる方法(FTDIのドライバを利用)を現在は使っています。
fenrir様
早速のご回答ありがとうございました。
infを拝見して納得いたしました。
その後色々と試したところ、XP+SP3なら正常動作することが分かりました。ただし、PCによって動作するのとしないのがあるようです。
私が試したのは、XP+SP2, XP+SP2+hotfix, XP+SP3, Vistaで、inf内でMIを指定するとどの組み合わせでもインストールは正常終了しますが、XP+SP3の組み合わせ以外ではCOMポートをOpenできませんでした。
とりあえず動く環境を一つでも構築できましたので、引き続き可能性を探っていきます。
本当にこちらの記事が参考になりました。ありがとうございました。
追)最初のコメントの中にメアドを書いてしまいました。お手数おかけいたしますが、お時間がある時に削除していただけますと幸いです。すみません。
Posted by: たろ : March 5, 2009 11:35 AMコメントする
- 匿名でのコメントは受け付けておりません。
- お名前(ハンドル名可)とメールアドレスは必ず入力してください。
- メールアドレスを表示されたくないときはURLも必ず記入してください。
- コメント欄でHTMLタグは使用できません。
- コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
- コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。
- 投稿ボタンを押してエラーがでなければ、投稿は成功しています。反映されるまでには少し時間がかかります。
作者様
はじめまして。たろと申します。
私は今CDC+HIDの実装にトライしております。
たまたま作者様のページを見つけて「これだっ」ってことでIADを追加して色々試してみました。
その中で確認させていただきたいことが出てきたのですが、infファイル中の[Models]においてインターフェース番号は指定されてますか?
私がトライした結果ではMI_00にしてもMI_01にしてもCOMポートは一つだけ追加になり、デバマネでポート番号を確認できますが、アプリからそのCOMポートをオープンしようとすると存在しないエラーとなります。
また、MIを指定しないとインストール時にCDC用のドライバを検出できません。
もし可能でしたらinfファイルを公開もしくは直メしていただけますととても助かります。
ご検討いただけますと幸いです。
たろ
Posted by: たろ : March 3, 2009 05:08 PM