日別アーカイブ: 2009年2月7日

HID の読み書きと Bluetooth の違いを吸収するために API を選択する方法

せっかくなのでもう少し送受信 API 周りを解説してみます。
前回 列挙して各デバイスのパスがわかったので、あとは Open して実際の通信を行います。
問題は Bluetooth stack によって使用可能な API が異なっていることです。

// デバイスの Open
HANDLE	hdev= CreateFile(
				path,
				GENERIC_READ|GENERIC_WRITE,
				FILE_SHARE_READ|FILE_SHARE_WRITE,
				NULL,
				OPEN_EXISTING,
				FILE_FLAG_OVERLAPPED,
				NULL
			);

if( !HidD_GetPreparsedData( hdev, &Ppd ) ){
	Close();
	return	FALSE;
}

HIDP_CAPS	caps;
if( !HidP_GetCaps( Ppd, &caps ) ){
	Close();
	return	FALSE;
}

// 必要なバッファサイズを調べておく。これを元にキューを作る。
InputByteLength= caps.InputReportByteLength;
OutputByteLength= caps.OutputReportByteLength;

● API テスト

コマンド送信に使う API を選択します。

WindowsVista 標準の bluetooth Stack では HidD_SetOutputReport() を使います。
ところが Toshiba bluetooth Stack / Bluesoleil ではこの命令が使えませんでした。

このあたり、各 stack による違いは下記のエントリでまとめています。
Toshiba bluetooth stack と Bluesoleil 対応

// テストコマンドを送信、直後の ReadFile() で Timeout 判定
if( !HidD_SetOutputReport(
		hDev,
		command,
		cmdlength
			) ){
	return	FALSE;
}

まず最初に HidD_SetOutputReport() を使って何らかのリターンがあるコマンドを
送信してみます。

この API が直接エラーを返す場合は WriteFile() の選択で決定です。ただしエラー
を返してくれるのは Toshiba Stack の場合だけ。Bluesoleil v5 ではエラー無しで
送信も出来ません。

判定の手順

(1) HidD_SetOutputReport() でリターンのあるコマンドを送信してみる。

(2) HidD_SetOutputReport() がエラーを返す場合は WriteFile() を選択で決定。
  Toshiba Bluetooth stack の場合。

(3) エラーが返らない場合は直後に ReadFile() でデバイスの返答を待ちます。

(4) 結果が返ってきたら HidD_SetOutputReport() を選択。Windows stack。

(5) Timeout 判定。一定時間待っても結果が来なければ Bluesoleil。
  送信は WriteFile() を選択する。

●データ送信

HidD_SetOutputReport() には送信するデータを直接渡すことが可能です。
たとえば 4byte なら 4byte のみで構いません。
WriteFile() を使う場合は、必ず OutputReportByteLength 分のバッファを作って
から転送を行います。

char*	bufp= Queue.WriteAlloc();
assert( length <= OutputByteLength );

if( !bufp ){
	// error
	return;
}
memcpy( bufp, command, length );

memset( &WriteOverlap, 0, sizeof(OVERLAPPED) );
WriteOverlap.hEvent= handle;
if( !WriteFileEx(
			hDev,
			bufp,
			OutputByteLength,
			&WriteOverlap,
			_WriteFileCB ) ){
	int	err= GetLastError();
	// error
}

このあたりも、成功するまで何度も試して調べた部分です。
Windows7 など Bluetooth のサポートも強化されるので、おそらく今後は
Windows stack の方が標準になっていくものと考えられます。
そのうちきっと HidD_SetOutputReport() だけ済む時代が来るでしょう。

関連エントリ
複数の HID から情報を読み出すには
Toshiba bluetooth stack と Bluesoleil 対応