• 締切済み

1つのデバイスにCDCクラスとHIDクラス実装できますか?

当方PIC18F4550を実験台に色々なUSB機器を作ろうと 楽しんでおります。 開発環境はWindowsXPでMPLAB IDE v8.43を利用しております。 コンパイラはC18を利用しております。 MicrochipよりMicrochip Application Libraries v2009-11-18を ダウンロードしてきてCDCやHIDをPIC18F4550へ秋月のライターを使って プログラミングしてみた所、2つとも正常に動かすことができました。 そこで、この2つのクラスを組み合わせて対話式キーボード(仮称)を 作ってみたくなりました。 概要は、PC上で動いているWindowsアプリケーション(C#)からUSB通信(CDCクラス) を利用して数値『1』を送信するとPIC18F4550はHIDクラスを利用して 『しばらくおまちください。』とPC上のメモ帳なりメッセンジャーなりに タイピングするようなデバイスを作りたいと思っております。 CDCクラスの送受信やHIDクラスのキー送信は実験済みで利用できておりますが、 この2つ1つのデバイスにプログラミングする所でつまずいてしまいました。 C#についても開発経験があり問題ありません。 1つのデバイスにCDCとHIDを入れるとデバイスマネージャー上では どうなるの?などなど・・・ 疑問が山済みです。 どなたか、この2つのクラスを1つのデバイスにプログラミングする方法や ヒントなどお持ちでしたら是非ご教授ください。 よろしくお願いいたします。

みんなの回答

回答No.7

No.6 > しかし、ポップアップで『ハードウェアのインストール中に・・・』となり正常に稼動しません。 >これはやはり (中略) >ここの記述が間違っているからなのでしょうか? 単純に考えるとそうなりますね。 両方のデバイスのセットアップまでいけているのであれば、 ・インターフェースディスクリプタのサブクラス ・エンドポイントディスクリプタの設定 あたりが怪しいとは思います。 逆に、今の状態でCDCの設定をコメントアウトしたらHIDは動作してますか? >ではよろしくお願いいたします。 さすがに現役を離れて久しい身で、使ったことのないシステムの類推が多いので、過度の期待はしないでくださいね。

回答No.6

No.5 >●当方が利用しているUSBフレームワークはMICROCHIP社が公開している > Microchip Application Libraries v2009-11-18 Installer.zipなの > ですが、こちらのHID/CDCはマルチファンクションに対応し > 構造になっているのでしょうか?? 軽く眺めましたが、CDCやHIDのソースは何を基準に選びましたか? 「USB Device - Composite - HID + MSD」のように、 最初からマルチファンクション用の構成もいくつかありましたよ? >●CDCとHIDのコンフィグレーションディスクリプタ、インターフェー > スディスクリプタ、およびエンドポイントディスクリプタは > configDescriptor1[]={ ここへ }全て記述すればいいのでしょうか? サンプルの構成からだと、「はい」となります。

neo_ts
質問者

補足

ご回答ありがとうございます。 >軽く眺めましたが、CDCやHIDのソースは何を基準に選びましたか? >「USB Device - Composite - HID + MSD」のように、 >最初からマルチファンクション用の構成もいくつかありましたよ? ●おぉ!本当だ!!  色々見てみないとだめですね。  抜け出せない所にはまると視野が狭くなってしまって・・・  早速3種類のComposite構成(HID+MSD / MSD+CDC / WinUSB+MSD)の  中からMSD+CDCを使ってみました。  Configuration Descriptorの中にInterface Association Descriptor  という物がありましてこれが恐らく要かな?  MSDの部分をHIDに変えて何度かビルドを試行錯誤してhexができましたが  やはりWindowsXPが認識してくれません。  正しく言うと、COMポートは正常に認識されて付属のWindowsアプリ  からConnectできました。Send Dataしても帰ってきませんがこの辺は  色々消して壊れている模様です。    問題はHIDです。  確かにヒューマンインターフェイスデバイスに認識されました。(2つ認識された!かなりの進歩?嬉)  しかし、ポップアップで『ハードウェアのインストール中に・・・』となり  正常に稼動しません。これはやはり  Device Descriptor  Configuration Descriptor  Interface Descriptor  Endpoint Descriptor  Interface Association Descriptor  ここの記述が間違っているからなのでしょうか? >サンプルの構成からだと、「はい」となります。 ●だいぶ確信に近づいてきた気がします。 ではよろしくお願いいたします。

回答No.5

No.1-4です。 >●この様な形で進めて行くと、かなり重複する変数が出てきますので > かなりの変数名を変更しなければ行けません・・・ > これでいいのでしょうか? デバイスディスクリプタは1つでいいです。 必要なのは ・コンフィグレーションディスクリプタのI/F数 ・CDC/HIDに対応したインターフェースディスクリプタ、およびエンドポイントディスクリプタ です。 No.4で回答した「==」の中だけが複数になります。 >Vendor IDやProduct IDは同じにすればいいのか?? マルチファンクションの場合は、インターフェースディスクリプタに宣言したサブクラスを使用します。 オールマイティ宣言を使用しても問題ありません。 質問のソース(データ定義)からだと、ホストPCからのディスクリプタの要求に対して定義された内容を返すルーチンがあるはずです。 まずは既存のものから、デバイスディスクリプタから順にどこかに定義を設定しているところがないか確認してみてください。 (ここで、マルチファンクションに対応した構造になっていないと、少し改造する必要が出てきますが。)

neo_ts
質問者

補足

いつもお世話になっております。 >デバイスディスクリプタは1つでいいです。 ●なるど!1つ大きな前進です。  デバイスディスクリプタは1つでいいという事は  usb_descriptors.c(CDCクラスから)と>usb_descriptors1.c(HIDクラスから)  という形でファイルを追加はしなくてもいいと言うことですね。  かなりの変数が重複するので、これは正しいのか??やっていて  半信半疑だったので少し雲が晴れました。 >No.4で回答した「==」の中だけが複数になります。 ●当方が利用しているUSBフレームワークはMICROCHIP社が公開している  Microchip Application Libraries v2009-11-18 Installer.zipなの  ですが、こちらのHID/CDCはマルチファンクションに対応した  構造になっているのでしょうか?? >・コンフィグレーションディスクリプタのI/F数 >・CDC/HIDに対応したインターフェースディスクリプタ、およびエンドポイントディスクリプタ です。 ●CDCとHIDのコンフィグレーションディスクリプタ、インターフェー  スディスクリプタ、およびエンドポイントディスクリプタは  configDescriptor1[]={ ここへ }全て記述すればいいのでしょうか? 本当に長々とすみません・・・ 何とか実現した案件なのでよろしくお願いいたします。

回答No.4

No.1-3です。 最初にお断りしておきますが、 ここから先は、ソース構成の問題なので的確な回答は難しいです。 (今までも、一応USBデバイスとPCドライバ両方の開発経験からの推測混じりで回答しています) >こんな形で定義していくと言うことでしょうか?? おそらくそんな形だとは思いますが、 実際にはホストからのディスクリプタ要求に対しての返信(ディスクリプタ送信)ルーチンがわからないため難しいです。 とりあえず、最低限必要なディスクリプタの知識だけ記載しておきます。 マルチファンクションは今回の質問からは 以下のような構成となります。 --------------------------------------- デバイス ディスクリプタ --------------------------------------- コンフィグレーション ディスクリプタ ======================================= インターフェース ディスクリプタ(1) --------------------------------------- エンドポイント ディスクリプタ  (必要なエンドポイント数分) ======================================= | | ======================================= インターフェース ディスクリプタ(n) --------------------------------------- エンドポイント ディスクリプタ  (必要なエンドポイント数分) ======================================= 上記の「===」でくくっている部分が認識させるデバイスごとに必要な部分です(CDCとHIDなら2つ)。 もう少し詳しくは以下のPDFの「2.IAD Model Example」にイメージ図があります。 http://www.usb.org/developers/whitepapers/iadclasscode_r10.pdf ひょっとしたら以下の方がわかりやすいかもしれません。 http://www.uquest.co.jp/ps/middleware/cs/usb06.html 注意事項はいくつかありますが、特に重要なところだけ。 ・総データ長 ・インターフェース数とNo. ・エンドポイントNo. の設定には特に注意してください。 私が言うのもなんですが、 回答の質もばらつきますし、言葉だけでは伝えるのも難しいところがありますので 以降もUSBに関わられるのなら技術書は何冊か購入しておいたほうがいいですよ。

neo_ts
質問者

補足

ご回答ありがとうございます。 しかし、どうしてもわかりません。 具体的にCDCクラスとHIDクラスを混在させる方法が・・・ >●という事は、usb_descriptors.c(CDCクラスから)と>usb_descriptors1.c(HIDクラスから)という形で・・・ ●この様な形で進めて行くと、かなり重複する変数が出てきますので  かなりの変数名を変更しなければ行けません・・・  これでいいのでしょうか?  もし、usb_descriptors.cとusb_descriptors1.cした場合  Vendor IDやProduct IDは同じにすればいいのか?? /* Device Descriptor (HID) */ ROM USB_DEVICE_DESCRIPTOR device_dsc= { 0x12, // USB_DESCRIPTOR_DEVICE, // 0x0200, // 0x00, // 0x00, // 0x00, // USB_EP0_BUFF_SIZE, // 0x09D8, // 0x005A, // 0x0001, // 0x01, // 0x02, // 0x00, // 0x01 // }; /* Device Descriptor (CDC) */ ROM USB_DEVICE_DESCRIPTOR device_dsc1= { 0x12, // USB_DESCRIPTOR_DEVICE, // 0x0200, // CDC_DEVICE, // 0x00, // 0x00, // USB_EP0_BUFF_SIZE, // 0x09D8, // 0x005A, // 0x0100, // 0x01, // 0x02, // 0x00, // 0x01 // }; こんな感じでしょうか?

回答No.3

No.1です。 >CDCクラスは正常に動いているのですが、HIDクラスの反応が >見られません・・・ まず確認です。 デバイスマネージャでHIDとCDCは「同じUSBハブの下に」認識されていますか? 「ディスクリプタ」の話をしたのはここに関係するからで、マルチファンクションデバイスの場合は「インターフェイスディスクリプタ」をデバイスクラス毎に用意する必要があります。 現状では、ホストPCがHIDを認識していないのではないかと思いますが……

neo_ts
質問者

補足

いつもいつも早々のご回答ありがとうございます。 >まず確認です。 >デバイスマネージャでHIDとCDCは「同じUSBハブの下に」認識されていますか? >「ディスクリプタ」の話をしたのはここに関係するからで、マルチファンクションデバイスの場合は「インターフェイスディスクリプタ」をデバイスクラス毎に用意する必要があります。 >現状では、ホストPCがHIDを認識していないのではないかと思いますが…… ●ご指摘の通り、USBをつないだ瞬間にCOMポートは更新されて使える  用になるのですが、HID(キーボード)の部分には何の変化も現れません。  今は、Microchip SolutionsのCDCクラスを利用し、そこにHID Keybordクラスを  追加しているのでCDCが認識されるのでしょうか?  逆にHIDクラスにCDCクラスを追加した場合にはHIDはホストに認識  されるのかな? >「インターフェイスディスクリプタ」をデバイスクラス毎に用意する必要があります。 ●という事は、usb_descriptors.c(CDCクラスから)とusb_descriptors1.c(HIDクラスから)という形で  参照して、 USB_DEVICE_DESCRIPTOR device_dsc={CDCクラスから}  configDescriptor1[]={CDCクラスから} USB_DEVICE_DESCRIPTOR device_dsc1={HIDクラスから}  configDescriptor2[]={HIDクラスから}  こんな形で定義していくと言うことでしょうか??

回答No.2

No.1です。 >●これから接続別に見る癖をつけたいと思います。 経験則ですが、USBデバイスがホストからハブを経由してどうつながっているかがわかりやすいので、 USB開発する人には勧めることにしています。 >●エンドポイントNO?? > HIDのusb_descripters.cの中を見ていたら (中略) >この記述がありましたが、この辺りから何か変更するのでしょうか? はい。あります。 まず、USBのPnPの仕組みをおおざっぱに説明しますが、 USBデバイスはホストと接続された場合に以下のような情報をやり取りします(一例であり他にもたくさんあります)。 ・デバイスクラス ・デバイスのメーカーコード/機器番号 ・使用するエンドポイントの構成 これらの情報を元に、ホストは最適なドライバーのロード(インストール)や通信データの送受信を行います。 この上記の情報が「ディスクリプタ」というデータブロックの中に含まれます。 つまり、この部分を理解していないとUSBデバイスの認識すらできないということになります。 余分な部分を飛ばすと、 >/* Endpoint Descriptor */ の >HID_EP | _EP_OUT, //EndpointAddress >HID_EP | _EP_IN, //EndpointAddress の部分がエンドポイントの定義です。 二つあるのは、送受信別々にエンドポイントが必要なためです。 専門的な話になりますが、USBデバイスは「4種類の転送モード」で「送受信」することができます。 USBはこの「転送モード」と「送信もしくは受信」で一つの論理的な回線を構築します。これを「エンドポイント」と言います。 エンドポイントの番号は特別の規定やH/Wの制限がない限り「(v1.1-2.0なら)1~15」までをデバイス作成者が自由に付けることができます。 CDCのように、「送信」と「受信」を行う為には最低二つ(正確にはEP0は必須の為3つ)のエンドポイントが必要です。 とりあえず USB.orgから仕様書は持ってきておいた方がいいです(特にHIDとCDCは)。 http://www.usb.org/home ディスクリプタについては以下が理解しやすいと思います(マルチファンクションではないです)。 http://www.picfun.com/usb04.html これはお約束の本ですが CQ出版の「インターフォース増刊 USBハード&ソフト開発のすべて」もあると便利かもしれません。 赤い方はちょっと内容が古いですが、v1.1時代のもので説明が細かいです。 青い方はv2.0メインの為、デバイス認識についてはちょっと省略されています。 尚、「Interface 2010年3月号」はUSB3.0特集で、最初にちょっとした基礎知識が記載してあります。

neo_ts
質問者

補足

早々のご回答ありがとうございます。 CDCクラスのusb_dicriptors.cにHIDのエンドポイントを usb_function_hid.hをmain.cからインクルードして何度も ビルドに失敗しながらビルドに成功しました。 CDCクラスは正常に動いているのですが、HIDクラスの反応が 見られません・・・ (CDCが文字を返してくる部分へHIDの文字送信関数を追加し確認) CDCを利用しているので#define USB_MAX_EP_NUMBERは4となるのでしょうか? もちろんROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={}も 追加しております。 何かまだ足りないのでしょうか?

回答No.1

http://bekkoame.okwave.jp/qa5653501.html の続きですね。返答しようとしても閉じられていたのでできませんでした。 以下は一般論で書きます。 >1つのデバイスにCDCクラスとHIDクラス実装できますか? できます。 「マルチファンクションデバイス」と呼ばれますが、わかりやすい例ではプリンターとスキャナー一体型の「複合機」がそれに該当します。 製品によっては内部にUSB-HUBを内蔵している場合もあるようですが、マルチファンクションデバイスとして実装されているものもあります。 >1つのデバイスにCDCとHIDを入れるとデバイスマネージャー上ではどうなるの? それぞれ別のデバイスとして認識されます。 尚、USB開発を行うなら、デバイスマネージャは「デバイス(接続別)」で見る癖をつけておくとよいです。 とりあえず、USBのディスクプリタの構成と内容を理解しないと、最初のデバイス認識で躓きます。 まずは、単一デバイスでエンドポイントNo.を変更することからやってるといいかもしれません。 (ここがわからないと、その先は……)

neo_ts
質問者

補足

SnowShower 様 引き続きご回答ありがとうございます。 いつも参考になり大変助かっております。 >「マルチファンクションデバイス」と呼ばれますが、わかりやすい例ではプリンターとスキャナー一体型の「複合機」がそれに該当します。 >製品によっては内部にUSB-HUBを内蔵している場合もあるようですが、マルチファンクションデバイスとして実装されているものもあります。 ●プリンタとスキャナー確かにそうですね。 >それぞれ別のデバイスとして認識されます。 >尚、USB開発を行うなら、デバイスマネージャは「デバイス(接続別)」で見る癖をつけておくとよいです。 ●これから接続別に見る癖をつけたいと思います。 >とりあえず、USBのディスクプリタの構成と内容を理解しないと、最初のデバイス認識で躓きます。 >まずは、単一デバイスでエンドポイントNo.を変更することからやってるといいかもしれません。 ●エンドポイントNO??  HIDのusb_descripters.cの中を見ていたら /* Configuration 1 Descriptor */ ROM BYTE configDescriptor1[]={ /* Configuration Descriptor */ 0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type DESC_CONFIG_WORD(0x0029), // Total length of data for this cfg 1, // Number of interfaces in this cfg 1, // Index value of this configuration 0, // Configuration string index _DEFAULT | _SELF, // Attributes, see usb_device.h 50, // Max power consumption (2X mA) /* Interface Descriptor */ 0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number 2, // Number of endpoints in this intf HID_INTF, // Class code BOOT_INTF_SUBCLASS, // Subclass code HID_PROTOCOL_KEYBOARD, // Protocol code 0, // Interface string index /* HID Class-Specific Descriptor */ 0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes RRoj hack DSC_HID, // HID descriptor type DESC_CONFIG_WORD(0x0111), // HID Spec Release Number in BCD format (1.11) 0x00, // Country Code (0x00 for Not supported) HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h DSC_RPT, // Report descriptor type DESC_CONFIG_WORD(63), //sizeof(hid_rpt01), // Size of the report descriptor /* Endpoint Descriptor */ 0x07,/*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_IN, //EndpointAddress _INTERRUPT, //Attributes DESC_CONFIG_WORD(8), //size 0x01, //Interval /* Endpoint Descriptor */ 0x07,/*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_OUT, //EndpointAddress _INTERRUPT, //Attributes DESC_CONFIG_WORD(8), //size 0x01 //Interval }; この記述がありましたが、この辺りから何か変更するのでしょうか?