標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第475回]
●HIDテストプログラム(HIDデバイス検出)のまとめ
前回までで、やっとUSBに接続されているHIDデバイスのProductIDとVenderIDが検出できるようになりました。
そのテストでは秋月のPICプログラマとともに、私がつくった試作回路(PIC18F4550回路)も接続して、ともに検出できることを確認しました。
ここから先は、ProductIDとVenderIDの検出に使ったhandleをそのまま使って、ターゲットデバイスに対してWriteFile関数とReadFile関数によって、データの送受信を行う部分の作業をしていくことになります。
ですけれど、やっとHIDデバイスの検出ができた、とは言っても、それはWindowsマシンの側のソフトができた、と言う話で、相手側のPICのプログラムについては、何もまだ説明をしておりません。
Windowsマシンの側のプログラムについてだけ、どんどん先に進んでいっても、相手側のプログラムをどう作っていくのかも説明しなければ、実際のところ、何もできないのと同じです。
ということで、やっとHIDデバイスの検出ができて、一区切りつきましたので、これから先はしばらくの間、いよいよPICの側のプログラムについて説明をしていきたいと思います。
その前に、今まで説明をしてきましたHIDテストプログラム(HIDデバイス検出)を簡単にまとめて整理しておくことにします(そうしておきませんと、また全部すっかりきれいに忘れてしまいます)。
ソースプログラムは、[第431回]にあります。
ですが、その後にWindowsXPでUSBマウスが検出できないことがわかり、そのための対策を書き加えました([第474回])ので、一部が変更になりました。
ですので、前回の修正を加えた、現在までのところの最終リストをまずお見せしたうえで、簡単な説明をしていくことにいたします。
●HIDテストプログラム(HIDデバイス検出)のソースリストです
//HID sample // //10/1/18 10/1/19 1/20 1/29 //2/6 2/7 4/5 4/7 4/9 //from hidtest1_8_b // #include <windows.h> #include <setupapi.h> extern "C" { #include "hidsdi.h" } #include <iostream.h> #pragma comment(lib, "hid.lib") void main( void ) { cout << hex; // // HIDclass識別子取得 // GUID hidGuid; HidD_GetHidGuid(&hidGuid); // // HIDデバイス情報セット取得 // HDEVINFO devinf; devinf = SetupDiGetClassDevs(&hidGuid, NULL, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); cout <<"devinf="<<devinf<<endl; // // 個別デバイス情報の構造体の取得 // SP_DEVICE_INTERFACE_DATA spid; spid.cbSize = sizeof(spid); // for( int index = 0; ; index++ ) { cout<<"search"<<endl; if(!SetupDiEnumDeviceInterfaces(devinf, NULL, &hidGuid, index, &spid)) { cout<<"end"<<endl; break; } cout<<"index="<<index<<endl; // // デバイスインターフェイスの詳細情報の取得 // unsigned long size; SetupDiGetDeviceInterfaceDetail( devinf, &spid, NULL, 0, &size, 0 ); PSP_INTERFACE_DEVICE_DETAIL_DATA dev_det = PSP_INTERFACE_DEVICE_DETAIL_DATA( new char[size] ); dev_det->cbSize=sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); // SetupDiGetDeviceInterfaceDetail( devinf, &spid, dev_det, size, &size, 0 ); cout << dev_det->DevicePath << endl; // // ファイルハンドルの取得 // HANDLE handle = CreateFile( dev_det->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if(handle==INVALID_HANDLE_VALUE){cout<<"INVALID_HADLE"<<endl;continue;} // // VenderIDとProductIDの取得 // HIDD_ATTRIBUTES attr; HidD_GetAttributes( handle, &attr ) ; cout<<"VenderID: " <<attr.VendorID <<endl; cout<<"ProductID: " <<attr.ProductID<<endl; cout<<endl; // CloseHandle(handle); } }
このプログラムは、ema log(http://emaame.com/20061227.html)様のサイトにありましたソースリストをもとに作成させていただきました。ema様には感謝申し上げます。
●MSDNのHIDclass関数情報
WindowsでHIDデバイスを扱うプログラムを書くためには、マイクロソフトが提供しているHIDclassAPIを利用することになります。
HIDclassAPIは、HID.DLL(HIDダイナミックリンクライブラリ)として¥windows¥systemフォルダに含まれています。
WindowsAPIの使い方などの情報は、マイクロソフトのMSDN情報サイトにあるはずなのですが、HIDclassAPIに関しては、どういうわけか、検索しても出てきません。
んなわけはないだろーよ、ということでしつこく検索してみましたら、どうやらHIDclassAPIについては、日本語のMSDNサイトには無い、ということのようです。
まーなんでしょうか、日頃先進国だの技術大国だのといばっていましても、所詮日本語などは、ハバ、なのですよねえ。
あ。ハバはナゴヤ弁でした。
ナゴヤ弁では、「仲間はずれ」にする、ということを、ハバにする、と申します。
んではということで、そのハバ、ではない、英語のMSDNサイト(http://msdn.microsoft.com/en-us/library/ff538865.aspx)を訪問いたしました。
●HIDclass識別子取得
さてでは、MSDNを参照しながら説明をしていくことにいたします。
最初はhidGuidの取得です。
HidD_GetHidGuid関数を使います。
GUID hidGuid; HidD_GetHidGuid(&hidGuid);
HDEVINFO devinf; devinf = SetupDiGetClassDevs(&hidGuid, NULL, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); cout <<"devinf="<<devinf<<endl;
SP_DEVICE_INTERFACE_DATA spid; spid.cbSize = sizeof(spid); // for( int index = 0; ; index++ ) { cout<<"search"<<endl; if(!SetupDiEnumDeviceInterfaces(devinf, NULL, &hidGuid, index, &spid)) { cout<<"end"<<endl; break; } cout<<"index="<<index<<endl;
unsigned long size; SetupDiGetDeviceInterfaceDetail( devinf, &spid, NULL, 0, &size, 0 ); PSP_INTERFACE_DEVICE_DETAIL_DATA dev_det = PSP_INTERFACE_DEVICE_DETAIL_DATA( new char[size] ); dev_det->cbSize=sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); // SetupDiGetDeviceInterfaceDetail( devinf, &spid, dev_det, size, &size, 0 ); cout << dev_det->DevicePath << endl;
HANDLE handle = CreateFile( dev_det->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if(handle==INVALID_HANDLE_VALUE){cout<<"INVALID_HADLE"<<endl;continue;}
HIDD_ATTRIBUTES attr; HidD_GetAttributes( handle, &attr ) ; cout<<"VenderID: " <<attr.VendorID <<endl; cout<<"ProductID: " <<attr.ProductID<<endl; cout<<endl;