標準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;