TNB Library
TnbUsbHid.h
[詳解]
1#pragma once
11#include "TnbCommunication.h"
12#include "TnbVector.h"
13#include "TnbUsbHidPathName.h"
14#include "TnbOverlapReader.h"
15
16
17
18//TNB Library
19namespace TNB
20{
21
22
23
58{
59 DEFSUPER(ICommunication);
60public:
61
63 explicit CUsbHid(void)
64 : m_hUpPipe(INVALID_HANDLE_VALUE), m_hDownPipe(INVALID_HANDLE_VALUE), m_sendTimeout(0)
65 , m_reportId(0), m_property(_T("HID"), TNBVIW_KIND_USB, 100)
66 {
67 ASSERT( m_property.receiveTimeout == 100 );
68 }
69
71 virtual ~CUsbHid(void)
72 {
73 Close();
74 }
75
81 virtual const TProperty& GetProperty(void) const
82 {
83 return m_property;
84 }
85
92 virtual bool Open(void)
93 {
94 Close();
95 // デバイスのオープン
96 DWORD x = (m_sendTimeout != 0) ? FILE_FLAG_OVERLAPPED : 0;
97 HANDLE hDown = ::CreateFile(
98 m_hidName.GetPathName(), GENERIC_WRITE,
99 (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, x, 0);
100 if ( hDown == INVALID_HANDLE_VALUE )
101 {
102 _GetLastError("CreateFile");
103 ::SetLastError(ERROR_NOT_FOUND);
104 return false;
105 }
106 HANDLE hUp = ::CreateFile (
107 m_hidName.GetPathName(), (GENERIC_READ | GENERIC_WRITE),
108 (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
109 if ( hUp == INVALID_HANDLE_VALUE )
110 {
111 _GetLastError("CreateFile");
112 // Read が出来なくても以下に続く。
113 }
114 m_hDownPipe = hDown;
115 m_hUpPipe = hUp;
116 //
117 TRACE0( "CHid::Openしました\n" );
118 m_property.typeName = CStr::Fmt(_T("HID-V%04X-P%04X"), m_hidName.GetVendorId(), m_hidName.GetProductId()); // タイプ名。
119 m_property.typeId = TNBVIW_KIND_USB + (reinterpret_cast<ULONG_PTR>(this) & 0xFFFF);
120 m_property.receivePacketSize = m_hidName.GetInputReportByteLength() - 1;
121 m_property.sendPacketSize = m_hidName.GetOutputReportByteLength() - 1;
122 m_reader.Attach(m_hUpPipe, m_property.receivePacketSize + 1);
123 return true;
124 }
125
129 virtual void Close(void)
130 {
131 m_reader.Detach();
132 //Portのクローズ
133 if ( m_hUpPipe != INVALID_HANDLE_VALUE )
134 {
135 m_CloseHandle(m_hUpPipe);
136 m_hUpPipe = INVALID_HANDLE_VALUE;
137 }
138 if ( m_hDownPipe != INVALID_HANDLE_VALUE )
139 {
140 m_CloseHandle(m_hDownPipe);
141 m_hDownPipe = INVALID_HANDLE_VALUE;
142 }
143 }
144
150 virtual bool IsOpened(void) const
151 {
152 return m_hDownPipe != INVALID_HANDLE_VALUE;
153 }
154
160 virtual bool IsConnect(void) const
161 {
163 if ( ::GetLastError() == ERROR_DEVICE_NOT_CONNECTED )
164 {
165 return false;
166 }
167 return IsOpened();
168 }
169
175 virtual bool CanSend(void) const
176 {
177 return (m_hDownPipe != INVALID_HANDLE_VALUE) && (m_hidName.GetOutputReportByteLength() > 0);
178 }
179
185 virtual bool CanReceive(void) const
186 {
187 return (m_hUpPipe != INVALID_HANDLE_VALUE) && (m_hidName.GetInputReportByteLength() > 0);
188 }
189
194 void SetReportId(BYTE id)
195 {
196 m_reportId = id;
197 }
198
206 virtual bool SetReceiveTimeout(DWORD to)
207 {
208 m_property.receiveTimeout = to;
209 return true;
210 }
211
220 virtual size_t Send(size_t size, LPCVOID P)
221 {
222 if ( ! CanSend() )
223 {
224 return INVALID_SIZE;
225 }
226 size_t sizeOutputReport = m_hidName.GetOutputReportByteLength();
227 size_t sentTotalSize = 0; // 送信済みデータサイズ合計
228 size_t sendSize = 0; // 送信データサイズ
229 CWorkMem work(sizeOutputReport);
230 work[0] = m_reportId; // REPORT_ID
231 const BYTE* lpbData = static_cast<const BYTE*>(P);
232 //
233 bool isSuccess = true;
234 //
235 while ( true )
236 {
237 if ( (size - sentTotalSize) < sizeOutputReport )
238 {
239 sendSize = size - sentTotalSize;
240 memset(work, 0, sizeOutputReport);
241 }
242 else
243 {
244 sendSize = sizeOutputReport -1;
245 }
246 // 送信データ 先頭は必ずREPORT_ID値とする(0x00 固定)
247 MemCopy(&work[1], &lpbData[sentTotalSize], sendSize);
248 // データ送信(NG時はリトライする(10回まで))
249 bool r = false;
250 loop ( i, 10 )
251 {
252 DWORD dwWriteLen = 0;
253 if ( m_Write(m_hDownPipe, work, ToDword(sizeOutputReport), &dwWriteLen) )
254 {
255 if ( sizeOutputReport == dwWriteLen )
256 {
257 r = true; //成功
258 break;
259 }
260 }
261 if ( _GetLastError("WriteFile") == ERROR_DEVICE_NOT_CONNECTED )
262 {
263 Close();
264 break;
265 }
266 }
267 if ( ! r )
268 {
269 //送信失敗
270 isSuccess = false;
271 break;
272 }
273 sentTotalSize += sendSize; // 送信済みサイズ
274 if ( size <= sentTotalSize )
275 {
276 break;
277 }
278 }
279 return isSuccess ? size : INVALID_SIZE;
280 }
281
290 virtual size_t Receive(size_t size, LPVOID _P)
291 {
292 if ( ! CanReceive() )
293 {
294 return INVALID_SIZE;
295 }
296 size_t sizeInputReport = m_property.receivePacketSize;
297 CWorkMem work(sizeInputReport + 1);
298 size_t r = m_reader.Read(work.Ref(), m_property.receiveTimeout);
299 if ( r != INVALID_SIZE && r != 0 )
300 {
301 r--;
302 if ( r > size )
303 {
304 r = size;
305 }
306 MemCopy(static_cast<BYTE*>(_P), work.Ref() + 1, r);
307 }
308 else
309 {
310 if ( ::GetLastError() == ERROR_DEVICE_NOT_CONNECTED )
311 {
312 Close();
313 }
314 }
315 return r;
316 }
317
323 virtual size_t GetReceivingDataSize(void) const
324 {
325 return INVALID_SIZE;
326 }
327
334 virtual EState Check(void) const
335 {
336 return IsConnect() ? CONNECTING : CLOSED;
337 }
338
343 virtual void Purge(void)
344 {
345 HidD_FlushQueue(m_hDownPipe);
346 }
347
355 DWORD SetHidPathName(const CUsbHidPathName& hidName)
356 {
357 if ( hidName.IsEmpty() )
358 {
359 return ERROR_NOT_FOUND;
360 }
361 return SetHidPathName(hidName.GetPathName());
362 }
363
371 DWORD SetHidPathName(LPCTSTR lpszPathName)
372 {
373 Close();
374 return m_hidName.SetPathName(lpszPathName);
375 }
376
384 void SetSendTimeout(DWORD to)
385 {
386 Close();
387 m_sendTimeout = to;
388 }
389
397 bool SetOutputReport(size_t dataSize, LPCVOID lpcvData)
398 {
399 if ( m_hidName.GetOutputReportByteLength() == dataSize )
400 {
401 return !! HidD_SetOutputReport(m_hDownPipe, const_cast<LPVOID>(lpcvData), ToDword(dataSize));
402 }
403 return false;
404 }
405
413 {
414 CByteVector vb;
415 size_t l = m_hidName.GetInputReportByteLength();
416 if ( l > 0 )
417 {
418 BOOL r = !! HidD_GetInputReport(m_hUpPipe, vb.GetBuffer(l), ToDword(l));
419 vb.ReleaseBuffer();
420 if ( ! r )
421 {
422 vb.Invalid();
423 }
424 }
425 return vb;
426 }
427
435 bool SetFeature(size_t dataSize, LPCVOID lpcvData)
436 {
437 if ( m_hidName.GetFeatureReportByteLength() == dataSize )
438 {
439 return !! HidD_SetFeature(m_hDownPipe, const_cast<LPVOID>(lpcvData), ToDword(dataSize));
440 }
441 return false;
442 }
443
452 {
453 CByteVector vb;
454 size_t l = m_hidName.GetFeatureReportByteLength();
455 if ( l > 0 )
456 {
457 BOOL r = !! HidD_GetFeature(m_hDownPipe, vb.GetBuffer(l), ToDword(l));
458 vb.ReleaseBuffer();
459 if ( ! r )
460 {
461 vb.Invalid();
462 }
463 }
464 return vb;
465 }
466
472 const CUsbHidPathName& GetName(void) const
473 {
474 return m_hidName;
475 }
476
482 size_t GetFeatureReportByteLength(void) const
483 {
484 return m_hidName.GetFeatureReportByteLength();
485 }
486
493 {
494 CUnicode s;
495 bool r = !! HidD_GetManufacturerString(m_hDownPipe, s.GetBuffer(256), 256 * sizeof(WCHAR));
496 s.ReleaseBuffer();
497 return r ? CStr(s) : _T("");
498 }
499
506 {
507 CUnicode s;
508 bool r = !! HidD_GetProductString(m_hDownPipe, s.GetBuffer(256), 256 * sizeof(WCHAR));
509 s.ReleaseBuffer();
510 return r ? CStr(s) : _T("");
511 }
512
519 {
520 CUnicode s;
521 bool r = !! HidD_GetSerialNumberString(m_hDownPipe, s.GetBuffer(256), 256 * sizeof(WCHAR));
522 s.ReleaseBuffer();
523 return r ? CStr(s) : _T("");
524 }
525
532 CStr GetIndexedString(INDEX index) const
533 {
534 CUnicode s;
535 bool r = !! HidD_GetIndexedString(m_hDownPipe, index, s.GetBuffer(256), 256 * sizeof(WCHAR));
536 s.ReleaseBuffer();
537 return r ? CStr(s) : _T("");
538 }
539
545 DWORD GetReceiveBufferCount(void) const
546 {
547 ULONG numberBuffers;
548 BOOLEAN r = HidD_GetNumInputBuffers(m_hDownPipe, &numberBuffers);
549 return r ? numberBuffers : 0;
550 }
551
560 {
561 return !! HidD_SetNumInputBuffers(m_hDownPipe, c);
562 }
563
564private:
565 bool m_CloseHandle(HANDLE h)
566 {
567 DWORD f;
568 if ( ! ::GetHandleInformation(h, &f) )
569 {
570 _GetLastError("GetHandleInformation");
571 return false;
572 }
573 return !! ::CloseHandle(h);
574 }
575 bool m_Write(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten)
576 {
577 if ( m_sendTimeout == 0 )
578 {
579 return !! ::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, NULL);
580 }
581 OVERLAPPED overLapped;
582 Zero(overLapped);
583 HANDLE hEvent = ::CreateEvent(NULL, FALSE, TRUE, NULL);
584 ::ResetEvent(hEvent);
585 overLapped.hEvent = hEvent;
586 BOOL r = ::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, &overLapped);
587 if ( r )
588 {
589 // 成功
590 }
591 else if ( ::GetLastError() == ERROR_IO_PENDING )
592 {
593 // 非同期読み取り操作の結果をチェックする。
594 ::Sleep(0);
595 switch ( ::WaitForSingleObject(overLapped.hEvent, m_sendTimeout) )
596 {
597 case WAIT_OBJECT_0:
598 r = ::GetOverlappedResult(hFile, &overLapped, lpNumberOfBytesWritten, FALSE);
599 break;
600 case WAIT_TIMEOUT:
601 case WAIT_ABANDONED:
602 case WAIT_FAILED:
603 default:
604 ::CancelIo(hFile);
605 r = FALSE;
606 break;
607 }
608 }
609 ::CloseHandle(hEvent);
610 return !! r;
611 }
612
613 HANDLE m_hUpPipe;
614 HANDLE m_hDownPipe;
615 CUsbHidPathName m_hidName;
616 TProperty m_property;
617 BYTE m_reportId;
618 COverlapReader m_reader;
619 DWORD m_sendTimeout;
620 friend class CUsbHidTest;
621};
622
623
624
625}; // TNB
通信関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
ファイル関係のヘッダ
USB HIDのパスネーム情報管理関係のヘッダ
配列型情報管理関係のヘッダ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
オーバーラップ入力管理クラス.
size_t Read(LPVOID _P, DWORD wait=0)
[読込] 読込み.
void Detach(void)
[設定] デタッチ.
void Attach(HANDLE hFile, size_t size)
[設定] アタッチ.
void ReleaseBuffer(void)
[操作] 割り当てたバッファを開放.
Definition: TnbStr.h:954
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
TYP * GetBuffer(size_t iLength=0)
[操作] 書き込みバッファ要求.
Definition: TnbStr.h:914
hid.dll アクセスクラス
BOOLEAN HidD_SetFeature(HANDLE hidDeviceObject, PVOID pReportBuffer, ULONG reportBufferLength)
[送信] 機能レポート送信
BOOLEAN HidD_SetNumInputBuffers(HANDLE hidDeviceObject, ULONG numberBuffers)
[設定] 入力バッファ数設定.
BOOLEAN HidD_GetFeature(HANDLE hidDeviceObject, PVOID pReportBuffer, ULONG reportBufferLength) const
[受信] 機能レポート受信
BOOLEAN HidD_GetNumInputBuffers(HANDLE hidDeviceObject, PULONG pNumberBuffers) const
[取得] 入力バッファ数取得.
BOOLEAN HidD_SetOutputReport(HANDLE hidDeviceObject, PVOID pReportBuffer, ULONG reportBufferLength)
[送信] Outputレポート送信
BOOLEAN HidD_GetProductString(HANDLE hidDeviceObject, PVOID pBuffer, ULONG bufferLength) const
[取得] Product 文字列取得
BOOLEAN HidD_GetInputReport(HANDLE hidDeviceObject, PVOID pReportBuffer, ULONG reportBufferLength) const
[受信] Inputレポート受信
BOOLEAN HidD_GetManufacturerString(HANDLE hidDeviceObject, PVOID pBuffer, ULONG bufferLength) const
[取得] Manufacturer 文字列取得
BOOLEAN HidD_FlushQueue(HANDLE hidDeviceObject)
[処理] キューフラッシュ.
BOOLEAN HidD_GetIndexedString(HANDLE hidDeviceObject, ULONG stringIndex, PVOID pBuffer, ULONG bufferLength) const
[取得] INDEXED 文字列取得
BOOLEAN HidD_GetSerialNumberString(HANDLE hidDeviceObject, PVOID pBuffer, ULONG bufferLength) const
[取得] SerialNumber 文字列取得
USB-HIDパスネーム情報管理クラス
size_t GetOutputReportByteLength(void) const
[取得] Outputレポート長取得
bool IsEmpty(void) const
[確認] 情報有無確認
const CStr & GetPathName(void) const
[取得] パスネーム取得
size_t GetInputReportByteLength(void) const
[取得] Inputレポート長取得
DWORD SetPathName(LPCTSTR lpszPathName)
[設定] パスネーム設定.
WORD GetProductId(void) const
[取得] プロダクトID取得
WORD GetVendorId(void) const
[取得] ベンダID取得
size_t GetFeatureReportByteLength(void) const
[取得] Featureレポート長取得
USB-HIDアクセスクラス
Definition: TnbUsbHid.h:58
virtual EState Check(void) const
[確認] チェック.
Definition: TnbUsbHid.h:334
virtual ~CUsbHid(void)
デストラクタ
Definition: TnbUsbHid.h:71
CStr GetManufacturerString(void) const
[取得] Manufacturer 文字列取得
Definition: TnbUsbHid.h:492
CUsbHid(void)
コンストラクタ
Definition: TnbUsbHid.h:63
virtual bool SetReceiveTimeout(DWORD to)
[設定] 受信待ち時間設定.
Definition: TnbUsbHid.h:206
bool SetFeature(size_t dataSize, LPCVOID lpcvData)
[送信] SetFeature
Definition: TnbUsbHid.h:435
virtual bool Open(void)
[処理] オープン.
Definition: TnbUsbHid.h:92
bool SetOutputReport(size_t dataSize, LPCVOID lpcvData)
[送信] SetOutputReport
Definition: TnbUsbHid.h:397
CStr GetProductString(void) const
[取得] Product 文字列取得
Definition: TnbUsbHid.h:505
virtual bool CanSend(void) const
[確認] 送信可能確認.
Definition: TnbUsbHid.h:175
void SetReportId(BYTE id)
[設定] レポートID設定.
Definition: TnbUsbHid.h:194
CByteVector GetInputReport(void) const
[受信] GetInputReport
Definition: TnbUsbHid.h:412
virtual void Purge(void)
[処理] パージ.
Definition: TnbUsbHid.h:343
const CUsbHidPathName & GetName(void) const
[取得] パスネーム情報取得
Definition: TnbUsbHid.h:472
CStr GetSerialNumberString(void) const
[取得] SerialNumber 文字列取得
Definition: TnbUsbHid.h:518
virtual bool IsConnect(void) const
[確認] 接続確認.
Definition: TnbUsbHid.h:160
DWORD SetHidPathName(LPCTSTR lpszPathName)
[設定] USB-HIDデバイス指定.
Definition: TnbUsbHid.h:371
void SetSendTimeout(DWORD to)
[設定] タイムアウト付き送信モード.
Definition: TnbUsbHid.h:384
virtual void Close(void)
[処理] クローズ.
Definition: TnbUsbHid.h:129
DWORD SetHidPathName(const CUsbHidPathName &hidName)
[設定] USB-HIDデバイス指定.
Definition: TnbUsbHid.h:355
virtual bool CanReceive(void) const
[確認] 受信可能確認.
Definition: TnbUsbHid.h:185
virtual bool IsOpened(void) const
[確認] オープン確認.
Definition: TnbUsbHid.h:150
virtual size_t Receive(size_t size, LPVOID _P)
[処理] 受信.
Definition: TnbUsbHid.h:290
CByteVector GetFeature(void) const
[受信] GetFeature
Definition: TnbUsbHid.h:451
virtual const TProperty & GetProperty(void) const
[取得] 性能取得.
Definition: TnbUsbHid.h:81
bool SetReceiveBufferCount(DWORD c)
[設定] 入力バッファ数設定.
Definition: TnbUsbHid.h:559
virtual size_t GetReceivingDataSize(void) const
[確認] 受信データ確認.
Definition: TnbUsbHid.h:323
CStr GetIndexedString(INDEX index) const
[取得] INDEXED 文字列取得
Definition: TnbUsbHid.h:532
size_t GetFeatureReportByteLength(void) const
[取得] Featureレポート長取得
Definition: TnbUsbHid.h:482
DWORD GetReceiveBufferCount(void) const
[取得] 入力バッファ数取得.
Definition: TnbUsbHid.h:545
virtual size_t Send(size_t size, LPCVOID P)
[処理] 送信.
Definition: TnbUsbHid.h:220
TYP * GetBuffer(size_t size=0)
[操作] データアドレス取得
Definition: TnbVector.h:745
void ReleaseBuffer(void)
[操作] データの管理を元に戻す.
Definition: TnbVector.h:805
void Invalid(void)
[操作] 無効状態にする
Definition: TnbVector.h:604
const TYP * Ref(void) const
[取得] ポインタ取得
Definition: TnbDef.h:712
DWORD ToDword(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:395
TNB::CStrT< TCHAR > CStr
文字列クラス
Definition: TnbStr.h:1785
void Zero(V &value)
[設定] ゼロクリア.
Definition: TnbDef.h:399
TNB Library
Definition: TnbDoxyTitle.txt:2
void MemCopy(T *_pDst, const void *pSrc, size_t len)
[複製] メモリコピー
Definition: TnbDef.h:376
性能プロパティ型.
size_t sendPacketSize
送信パケットサイズ。INVALID_SIZE なら制限なし。
DWORD receiveTimeout
受信待ち時間。 INFINITE ならブロックされる。
size_t receivePacketSize
受信パケットサイズ。INVALID_SIZE なら制限なし。
通信インターフェース
@ CONNECTING
オープン&接続状態
@ CLOSED
クローズ状態