[C#][USB] Host apllication on WindowsXP with C#

2008/08/30工作::USBimport

★本気時は書きかけのものです.頓挫する前に公開★

PC側のソフトを準備する

氏のsample"generichid_cs"から,必要なコードを流用する.C#では,Win32APIの呼び出しを直接行うことはできない.unsafe codeとして,DLLからAPIをimport宣言してやる必要がある.VBでWin32APIを用いるために宣言していたのと同様である.*1

*1 : .NET環境ではC#もVBも同じILに落ちると思いますけど

HostTest_01

  • device enumeration
  • detection of device attached/detattached
  • IN/OUT transaction check by using ReadFile/WriteFile

console applicationでもよさそうだが,今後のことを考えてGUIで作っていく.Formに配置するリソースを列挙する.

  • TextWindow or List Window
    • Status Window
    • Rx Data window(StatusWindowに書いておけばいいか?)
  • EditBox
    • Device ID
      • VID
      • PID
      • IF-ID
    • TxData
  • コマンドボタン
    • device detect
    • INPUT
    • OUTPUT

パクリ

下記のファイルをコピーする.ただし,VBのnamespaceも使ってるようなので,少し綺麗にしたいと思た.ちうことで,VBのlength/CRLFだけを使っていたので,これを排除しただけなんですがね.

  • Debugging.cs
  • DebuggingDeclarations.cs
  • DeviceManagement.cs
  • DeviceManagementDeclarations.cs
  • FileIODeclarations.cs
  • Hid.cs
  • HidDeclarations.cs


device enumeration

detection of device attached/detattached

IN/OUT transaction check by using ReadFile/WriteFile



HostTest_02

Include all functions of HostTest_01.


メモ

device change

WM_DEVICECHANGEメッセージが通知される模様.標準でフックできないようなので,WindowProcedureをoverrideしてsniffする.

class DeviceManagement(In file DeviceManagement.cs)

attached/removed検出
登録: RegisterForDeviceNotifications()
停止:StopReceivingDeviceNotifications()
DeviceManagement::Boolean DeviceNameMatch( Message m, String mydevicePathName )

WM_DEVICECHANGEメッセージを受けて,pathnameとマッチするかチェックする.マッチする場合はtrueを返す.

DeviceManagement::Boolean FindDeviceFromGuid( System.Guid myGuid, ref String[] devicePathName )

Uses SetupDi API functions to retrieve the device path name of an attached device that belongs to an interface class.


SetupDi APIを使って,interface classに属する接続されたdevice path nameを検索する.


参照資料

★MSDNより,C#で Num Text boxの作成 - 派生させてHex Edit boxでも作れ..~ 入力: hexのみ, 出力:':'区切りで表示, nibbleでfocus失うなら捨てる. 入力中は文字色変えるとか.

http://msdn.microsoft.com/ja-jp/library/ms229644(VS.80).aspx http://msdn.microsoft.com/en-us/library/ms790920.aspx http://msdn.microsoft.com/ja-jp/library/cc429201.aspx

USB keyboardのテスト

2008/08/28工作::USBimport

USB keyboardの話

HIDとして,キーボードとマウスは抑えておきたいところである.そこで,キーボードについて,仕様ではよくわからなかった動作について確認する.PCやOSに依存するかもしれないので,ここで記述する事項は実際に試したこと,推測(妄想)事項であることを明記しておく.
何らかの明確な動作に関する資料が開示されているのであれば,ポインタを教示いただきますと幸いです.

実験と確認

先日の疑問について,実装して確認する.
デバイス側のマイコンから,キーコード(usage ID)を送信し,PC側でどういう挙動を示すかを調べる.

(1)	{0x00, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(3)	{0x00, 0, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A },
(4)	{0x00, 0, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06 },
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space

	結果.
	"abcdefg "の繰り返しとなる.
	 456789a

	"押している"情報であることがわかる.
	(1)-(2)で 'a'を2回送っていることになるはず.(2回数はshift押下)
	(3),(4)で並びを変えてみたが, 反応ナシ.
	(5)で全部離したと認識して, "bcdefg"をinput.
	このとき,押下情報(3)の若い順に入力されたと考えられる.(並びを変えて確認要)

	また,別キーボードにてshiftを押下したところ,押下中は文字サイズが変わった.

# 教訓.スキップせずにコツコツと進みましょう:)

"abcdefg "....

(1)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x00, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(3)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(4)	{0x00, 0, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06 },
(5)	{0x00, 0, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00 },
(6)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	"adefgbc "で繰り返された.
	(1) 'a'を押下,
	(2) 'a'を押下しながら shift押下
	(3) 'a'とshiftを同時に離す. 
	 → (shiftはキーの前後でon状態を保つ必要がある? 少なくとも入力時に同時か一つ前?)
	(4) d,e,f,g,b,c を押下
	(5) 'g'だけ離す...
	(6) b-fを離して, spaceを押す.


(1)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x01, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(3)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(4)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00 },
(7)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(8)	{0x00, 0, 0x05, 0xC6, 0x00, 0x00, 0x00, 0x00 },
(9)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(A)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	^a
	^a
	def
	0xC4/0xC6は無視されたぽいな..
	b
	<space>


!ここでReport descriptorのUsage Maxが 0x65なのに気づく.
0xE7とすることで,定義値全て有効になるはず..

(1)	{0x02, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x02, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(3)	{0x02, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(4)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00 },
(7)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(8)	{0x00, 0, 0x05, 0xC6, 0x00, 0x00, 0x00, 0x00 },
(9)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(A)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	ならなかったなぁ.
	AAdefb "Shift"は同時に離しても,跡で開放でも良いみたい.

min.max.を 0x80 - 0x7Fにしてみた.
	→値全部無視された.SHIFTのみに反応して,"固定キー機能"ダイアログが出てくる.

0x00 - 0x00E7にしてみたが,駄目だな. 
keypadになると,usage sub-IDが変わってくるので,無視されるのだろう.
table中,keyboard/keypadと明記されていたのはコレによるものと思われる.
分けてくれよ...

utility関数の作成

usage IDとASCIIコードとはテーブル引きするしかなさそう.US keyboardをベースにしているらしく,日本語keyboardとは異なるマップと考えるしかない.また,SHIFT/CTRL等の情報は文字とは別です.
前述の結果より,本I/FでPCが受信するのはキーの押下情報であり,入力された文字情報ではないです.文字入力の肩代わりをさせる場合,ほかのキーボードとの干渉を考慮する必要がありそうです.
ゲームの入力装置として考える場合は,押下情報であったことは良いことでしょう.同時押し6つまで認識してくれそうです.(SHIFT/ALT/CTRLは別腹で同時押し可)

ASCII文字 - 0x20を index0として,下記のIDを送ると良い.
ただし,"SHIFT+"は,SHIFTを押下しながら文字を入力した場合であり,単純に1倍との送信では実現できない.

0x2C, SHIFT+0x1E, SHIFT+0x34, SHIFT+0x20, SHIFT+0x21, SHIFT+0x22, SHIFT+0x24, 0x34, SHIFT+0x26, SHIFT+0x27, SHIFT+0x25, SHIFT+0x2E, 0x36, 0x2D, 0x37, 0x38,
	// 0x20~0x2F, → <SPC>!"#$%&'()*+,-./
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, SHIFT+0x33, 0x33, SHIFT+0x36, 0x2E, SHIFT+0x37, SHIFT+0x38
	// 0x30~0x3F, → 0123456789:;<=>?
SHIFT+0x1F, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
	// 0x40~0x4F, → @ABCDEFGHIJKLMNO
	// 0x89 : Keyboard International3(17) => '\'キー
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x2F, 0x31 ,0x30, SHIFT+0x23, SHIFT+0x2D,
	// 0x50~0x5F, → PQRSTUVWXYZ[\]^_
0x34, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
	// 0x60~0x6F, → `abcdefghijklmno
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, SHIFT+0x2F, SHIFT+0x31, SHIFT+0x30, SHIFT+0x32, 0x2A
	// 0x70~0x7F, → pqrstuvwxyz{|}~<DEL>


複合デバイスの作成

作り方

PSoC環境を使う限り,自動的にInterface数を把握して,standard requestに応答してくれる模様.便利ですな.. *1

  1. Descriptorにinterfaceを追加する.
  2. EPを追加する.
  3. Report descriptorを追加する.

メモ
PSoCのEPは,入出力で同じIDが使えない?simple IOの実装でEPを1/1または3/3としたときに,IN応答が無かった.OUTを受けてからIN transactionを起こしていたので,先に処理したモン勝ちか?詳細はPSoCのTRMで確認する予定.
【宿題】の結果,下記の記述が見つかりました.

PSoC TRM, Document No. 001-14463 Rev. **
34. Full-Speed USB

The SIE supports five endpoints including a control endpoint (endpoint 0) and four data endpoints (endpoint 1, 2, 3, and4).
The control endpoint can be configured to support SETUP, IN, and OUT requests.
The data endpoints can be individually configured to respond to Interrupt, Bulk, or Isochronous IN or OUT requests.

ということで,EP1~4は,INかOUTのいずれか1つしか取れません.したがって,インタフェースIN/OUTを2つ用いるデバイスでは,EPも2つ消費します.入出力対応しているEPであれば,EP数を削減できたのですが.まぁ,物理的な制約であり,仮に入出力OKでも,IDが経るなら同じなので,こんなもんなんでしょう.
キーボード,マウス,+α(入出力)とするならば,キーボードのLED出力は受け取れないということですね.

デバッグ・お試し時のメモ

PID/VIDが同じだと,Windows Device ManagerがInterfaceを覚えているようだ.
複合→単純に変えたとき,2度目以降は複合として扱われた.
Device Manager → USBコントローラ の 該当するVID/PIDの複合デバイスを削除することで,再度認識してくれるみたいです.


*1 : 仕組みを理解する上では,手抜きになってしまうなぁ.

参考サイト



wiki機能でコンテンツにしているけれども,まとまってないな...
日々書き散らかしてまとめていないからかなぁ.使い方間違ってる?w

USB関連覚書

2008/08/26工作::USBimport

資料入手先等

仕様書関連

個人サイト等実装例

  • The HID Page, Jan Axelsonさん, [http://www.lvr.com/:Jan Axelson's
    ある意味総本山?ホスト側ソフトも充実していて,さらにリンクも良い.

Lakeview Research]

2008/08/26(火)[USB][HID] キーボードとマウスと.(その1)

USB接続のキーボード・マウス・GPIOを増設する

という目的をあげました.いろいろ着手しかかりで,どれも完結してないのはご愛嬌:)

コレも2年ほど前にGPIO+CapSenceやろうとして,頓挫したままになっていたプロジェクトです.せっかく復帰したので,基本的なUIのキーボードとマウスの機能も持たせたいと思います.

前提条件と手順は,以下のとおりとします.

  • ホストは Windows XP,開発環境は...任意w
  • cypress のPSocであるところの,CY8C24894を使う
  • マイコンとPCとをつないで,デバイスの認識を行う
  • HIDデバイスとして認識させ,Windows標準ドライバを用いることでドライバの開発を避ける
  • キーボード押下情報の送達確認
  • マウス操作情報の送達確認
  • 汎用IOとしての,マイコンとのデータ授受確認(非USB-UART Bridge)

注:正しい用語を使って説明できていないです.作業メモとしてざっと書いているのでご容赦を.もし万が一,パクられる参照される時は,ものの本を見ながら単語の修正をしたほうがいいです.


マイコンとPCとをつないで,デバイスの認識を行う

何もナシだと辛いので,とりあえず検索してみましょう.ただし,手元に資料も欲しいので,後述する資料をそろえておくことを推奨いたします.*1

HIDとしてテキトウIOデバイスを作る

まずは,参照場所-個人(1)を追いかけてみます.
PSoC Designer ver.5でnew projectを作って,USBFSモジュールを追加, Wizardでdescriptorを記述していきます.本家のツール*2よりも使いやすくてイイデスネ.
サクサクと終わるかと思いきや,PCからHIDデバイス,という認識まではされたけれども,ドライバがinstallされない事態に.デバイスマネージャでUSB/HIDのアタリをあさってみると,黄色いびっくりマークがついてます.propertyでVID/PIDを見ると,確かに作ったデバイスです.Setupは飛んでいるみたいですが,どこかで調子悪くなっているようです.昔々に同じことになっていた記憶が・・・.

packetが見たい

さて,何もいわずに黄色いびっくりマークを出すだけで,何を言いたいのかわかりません.そこで,USBのプロトコルアナライザーでもあればスイスイ?なのですが,(検閲削除)なので,ソフト的に対処してしまいます.
探してみると,USB Snoopy Proというフリーソフトが出てきました.使い方は解凍してでてくるREADME.TXTのとおりです.見ずにやるとうごかねぇぞゴルァとなるかもしれません:)

結果,どうやらHID Report descriptorを受けたあとで,RESET PIPEなるコマンドが飛んでいます.Descriptorの記述に不満がるようです...HIDの面倒なところはココですね.
参照個人サイト(1)の,絵を見ながらまねていたのですが,下記2点のミスによるものでした.

  1. 見落としがあったこと
  2. 見ているうちにマウススクロールでHID-ReportではなくHID-Physicalになっていた

これに気づくまでにいろいろと検索したり,本を見たりして時間を費やしてしまいましたわ.まぁ,次の予習になったので結果オーライってところでしょうかね.


キーボードとマウスもつけたい

汎用IOだけだと面白くない.せっかくなので,キーボードとマウス機能もつけてしまいましょう.
どうやって複数機能を持たせるのかナァと不思議に思っていましたが,今は納得.

同じように疑問を持っている人がいた*3ので,さくっと解決.HID Report Descriptorで,複数の機能を宣言するだけでよい.それにあわせて,EndPointもしっかりと割り振ってやる必要があるけれども..

やり方がわかったら早速実験.PSoC DesignerでUSBFSのdescriptorを編集していきます.これまたびっくりマークに悩まされたりするわけですが...
詳細は後日.とりあえず認識するまでのダイジェストだけ.

  • EP1は OUT INTERRUPT, MaxPacketSize=8. キーボード
  • EP2は OUT INTERRUPT, MaxPacketSize=8. マウス
  • EP3は OUT INTERRUPT, MaxPacketSize=32. マイコン通信用
  • EP4は IN INTERRUPT, MaxPacketSize=32, マイコン通信用
  • Packet Sizeは Report descriptorのサイズ以上ならOK
  • HID spec.のappendixにあるキーボードにはOUTもあるが,削除可能.これでEPを稼ぐ.複数キーボードがある状態で,制御キー(?)のLock状態が見えないようになるのではないか?(要確認)
  • HID Report Descriptorの書式は理解しづらかった.仕様書・書籍・WEB Site,実機をいじくってなんとなく理解したつもり..?

今日はココまで.乞うご期待(ぉ


*1 : WEBに書かれている個人の発信を全て丸呑みにせず,必ず本家の資料を見るように心がけましょう.

*2 : HID Descriptor Tool,dt2_4.zipというファイル.

*3 : usb.orgの掲示板にて,質問されてました.回答は日本人(^^;

今回の参照場所

書籍

USB 2.0とUSB On-The-Goを含むカスタムUSBデバイス開発のすべて USBコンプリート[第3版]
仕様書直訳したような文章ですが,すらすらと仕様書が読めない方(オレオレ),紙面で資料を持っていたい方にオススメ.下記のようにWEBで情報公開されている方も多いので,動くものをエイヤで作るだけならイラナイかもしれない.でもまぁ暇つぶしに読んでおくこともオススメする.


WEBサイト

(0) 総本山usb.org

何はともあれココから始まる.仕様書の類は一通り落としておきましょう.HID usage tableや descriptor情報など,必須な情報ばかりです.このアタリの情報をあわせて記述しているサイトがあまり見当たらなかったので,本記事を書くことにしました.
本日は記載しませんが,まとめてwikiネタとしてコンテンツにしておきます.動作確認できてから・・・.

(1) Flatol Lab

PSoCにおけるUSBと題して,モロに同じ石です.開発環境が1つ前のDesigner 4で紹介されていますが,操作方法は ほぼは同じです.

(2) PSoCでUSB

Snoopyの検索でヒットしました.みなさん考えること/やることは同じですね:)

(3) USB HID Notes

キーボード・マウスのReport descriptorと,デバイスから放り出すときのメモリイメージを参照.