TNB Library
TnbRs232cEx.h
[詳解]
1#pragma once
14#include "TnbRs232c.h"
15#include "TnbThread.h"
16
17
18
19//TNB Library
20namespace TNB
21{
22
23
24
25#ifndef _TnbDOXYGEN //Document作成用シンボル
26
27class COverlapped : CCopyImpossible
28{
29public:
30
32 COverlapped(void) : m_hEvent(NULL)
33 {
34 Zero(m_overLapped);
35 }
36
38 ~COverlapped(void)
39 {
40 if ( m_hEvent != NULL )
41 {
42 ::CloseHandle(m_hEvent);
43 m_hEvent = NULL;
44 }
45 }
46
52 operator OVERLAPPED*(void)
53 {
54 Zero(m_overLapped);
55 if ( m_hEvent == NULL )
56 {
57 m_hEvent = ::CreateEvent(NULL, FALSE, TRUE, NULL);
58 ::ResetEvent(m_hEvent);
59 }
60 ::ResetEvent(m_hEvent);
61 m_overLapped.hEvent = m_hEvent;
62 return &m_overLapped;
63 }
64
73 size_t GetResult(HANDLE h, DWORD wait = 0)
74 {
75 if ( ::GetLastError() == ERROR_IO_PENDING )
76 {
77 // 非同期読み取り操作の結果をチェックする。
78 ::Sleep(0);
79 DWORD work = 0;
80 if( ::GetOverlappedResult(h, &m_overLapped, &work, FALSE) )
81 {
82 return work;
83 }
84 else if ( ::GetLastError() != ERROR_IO_INCOMPLETE )
85 {
86 return INVALID_SIZE;
87 }
88 }
89 size_t result = INVALID_SIZE;
90 DWORD r = 0;
91 switch ( ::WaitForSingleObject(m_overLapped.hEvent, wait) )
92 {
93 case WAIT_OBJECT_0:
94 if ( ::GetOverlappedResult(h, &m_overLapped, &r, FALSE) )
95 {
96 result = r; // 成功
97 ::CancelIo(h);
98 }
99 break;
100 case WAIT_TIMEOUT:
101 result = 0;
102 break;
103 case WAIT_ABANDONED:
104 case WAIT_FAILED:
105 default:
106 ::CancelIo(h);
107 break;
108 }
109 return result;
110 }
111 HANDLE m_hEvent;
112 OVERLAPPED m_overLapped;
113};
114
115#endif //_TnbDOXYGEN
116
117
118
132{
133 DEFSUPER(CRs232c);
134public:
135
145 {
147 virtual ~IListener(void) {}
148
163 virtual void OnRs232cEvent(DWORD event) = 0;
164 };
165
166
167 //-----------------------------
168
169
171 CRs232cEx(void) : m_propertyEx(_T("RS232C"), TNBVIW_KIND_RS232C), m_pListener(NULL)
172 {
173 m_propertyEx = _super::GetProperty();
174 m_propertyEx.receiveTimeout = 300;
175 m_eventMask = EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY | EV_CTS | EV_DSR | EV_RLSD | EV_BREAK;
176 m_eventMask |= EV_ERR | EV_RING | EV_PERR | EV_RX80FULL | EV_EVENT1 | EV_EVENT2;
177 }
178
181 {
182 Close();
183 }
184
185
199 void SetListenEvent(DWORD event)
200 {
201 m_eventMask = event;
202 }
203
209 {
210 m_pListener = P;
211 }
212
218 virtual const TProperty& GetProperty(void) const
219 {
220 return m_propertyEx;
221 }
222
230 virtual bool SetReceiveTimeout(DWORD to)
231 {
232 m_propertyEx.receiveTimeout = to;
233 return true;
234 }
235
241 virtual bool Open(void)
242 {
243 bool r = _super::Open();
244 m_propertyEx.typeName = _super::GetProperty().typeName;
245 m_propertyEx.typeId = _super::GetProperty().typeId;
246 if ( r )
247 {
248 m_thread.SetRunner(this);
249 return m_thread.Start();
250 }
251 Close();
252 return false;
253 }
254
258 virtual void Close(void)
259 {
260 ::SetCommMask(GetHandle(), 0);
261 _super::Close();
262 m_thread.Stop();
263 m_propertyEx.typeName = _super::GetProperty().typeName;
264 m_propertyEx.typeId = _super::GetProperty().typeId;
265 }
266
267
276 virtual size_t Receive(size_t size, LPVOID _P)
277 {
278 if ( size == 0 || m_propertyEx.receiveTimeout == 0 )
279 {
280 DWORD dwErrors;
281 COMSTAT tComStat;
282 if ( ! ::ClearCommError(GetHandle(), &dwErrors, &tComStat) )
283 {
284 _GetLastError("ClearCommError");
285 return INVALID_SIZE;
286 }
287 if ( size > tComStat.cbInQue )
288 {
289 size = tComStat.cbInQue;
290 }
291 if ( size == 0 )
292 {
293 return 0;
294 }
295 }
296 size_t redSize = 0;
297 if ( ReadPort(redSize, _P, size, GetHandle()) )
298 {
299 return redSize;
300 }
301 return INVALID_SIZE;
302 }
303
309 {
310 return m_thread;
311 }
312
313protected:
314
322 virtual DWORD Run(void)
323 {
324 ::SetCommMask(GetHandle(), m_eventMask);
325 DWORD event;
326 while ( IsRunnable() )
327 {
328 ::WaitCommEvent(GetHandle(), &event, m_eventOverlapped);
329 if ( ::GetLastError() != ERROR_ACCESS_DENIED )
330 {
331 DWORD r = m_eventOverlapped.GetResult(GetHandle(), INFINITE);
332 if ( r == sizeof(DWORD) )
333 {
334// TRACE1("★ RS232C Event = 0x%04X\n", event);
335 if ( m_pListener != NULL )
336 {
337 m_pListener->OnRs232cEvent(event);
338 }
339 if ( event == 0 )
340 {
341 break;
342 }
343 }
344 }
345 else
346 {
347 ::SetCommMask(GetHandle(), m_eventMask);
348 }
349 }
350 return 0;
351 };
352
360 virtual HANDLE CreatePort(LPCTSTR lpszPortName) const
361 {
362 DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE; // アクセス (読み取りおよび書き込み) モード
363 DWORD flag = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
364 HANDLE h = ::CreateFile(lpszPortName, desiredAccess, 0, NULL, OPEN_EXISTING, flag, NULL);
365 _GetLastError("CreateFile");
366 return h;
367 }
368
379 virtual bool WritePort(size_t& _writtenSize, size_t len, LPCVOID P, HANDLE h) const
380 {
381 DWORD dwWritten = 0;
382 ::WriteFile(h, P, ToDword(len), &dwWritten, m_writeOverlapped);
383 dwWritten = m_writeOverlapped.GetResult(h, INFINITE);
384 if ( dwWritten == INVALID_SIZE )
385 {
386 return false;
387 }
388 _writtenSize = dwWritten;
389 return true;
390 }
391
402 virtual bool ReadPort(size_t& _redSize, LPVOID _P, size_t len, HANDLE h) const
403 {
404 DWORD dwRed = 0;
405 ::ReadFile(h, _P, ToDword(len), &dwRed, m_readOverlapped);
406 dwRed = m_readOverlapped.GetResult(h, m_propertyEx.receiveTimeout);
407 if ( dwRed == INVALID_SIZE )
408 {
409 return false;
410 }
411 _redSize = dwRed;
412 return true;
413 }
414
415private:
416 DWORD m_eventMask;
417 IListener* m_pListener;
418 TProperty m_propertyEx;
419 mutable CThread m_thread;
420 mutable COverlapped m_readOverlapped;
421 mutable COverlapped m_writeOverlapped;
422 mutable COverlapped m_eventOverlapped;
423};
424
425
426
427}; // TNB
RS232Cのアクセス関係のヘッダ
スレッド管理関係のヘッダ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
拡張RS232Cアクセスクラス.
Definition: TnbRs232cEx.h:132
CThreadStatus & ReferThreadStatus(void)
[参照] 監視スレッド状態参照.
Definition: TnbRs232cEx.h:308
void SetListener(IListener *P)
[設定] リスナー登録.
Definition: TnbRs232cEx.h:208
virtual bool SetReceiveTimeout(DWORD to)
[設定] 受信待ち時間設定.
Definition: TnbRs232cEx.h:230
virtual bool Open(void)
[処理] オープン.
Definition: TnbRs232cEx.h:241
CRs232cEx(void)
コンストラクタ
Definition: TnbRs232cEx.h:171
virtual bool WritePort(size_t &_writtenSize, size_t len, LPCVOID P, HANDLE h) const
[通知] ポート書き込み.
Definition: TnbRs232cEx.h:379
virtual bool ReadPort(size_t &_redSize, LPVOID _P, size_t len, HANDLE h) const
[通知] ポート読み込み.
Definition: TnbRs232cEx.h:402
virtual HANDLE CreatePort(LPCTSTR lpszPortName) const
[通知] ポート作成.
Definition: TnbRs232cEx.h:360
virtual void Close(void)
[処理] クローズ.
Definition: TnbRs232cEx.h:258
virtual DWORD Run(void)
[動作] スレッド処理本体
Definition: TnbRs232cEx.h:322
virtual size_t Receive(size_t size, LPVOID _P)
[処理] 受信.
Definition: TnbRs232cEx.h:276
virtual const TProperty & GetProperty(void) const
[取得] 性能取得
Definition: TnbRs232cEx.h:218
~CRs232cEx(void)
デストラクタ
Definition: TnbRs232cEx.h:180
void SetListenEvent(DWORD event)
[設定] 監視するイベント指定.
Definition: TnbRs232cEx.h:199
RS232Cアクセスクラス
Definition: TnbRs232c.h:72
HANDLE GetHandle(void) const
[取得] ハンドル取得
Definition: TnbRs232c.h:339
スレッド状態管理クラス
Definition: TnbThread.h:128
スレッド管理クラス
Definition: TnbThread.h:316
bool SetRunner(IRunner *pRunner)
[設定] ランナー、設定
Definition: TnbThread.h:420
bool Stop(DWORD dwWait=15000)
[設定] スレッド停止 スレッドに対して停止要求します。
Definition: TnbThread.h:505
bool Start(LPCTSTR lpszName=NULL)
[設定] スレッド開始
Definition: TnbThread.h:618
DWORD ToDword(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:395
void Zero(V &value)
[設定] ゼロクリア.
Definition: TnbDef.h:399
TNB Library
Definition: TnbDoxyTitle.txt:2
拡張RS232Cイベントリスナー
Definition: TnbRs232cEx.h:145
virtual ~IListener(void)
デストラクタ
Definition: TnbRs232cEx.h:147
virtual void OnRs232cEvent(DWORD event)=0
[通知] イベント通知.
スレッド実行管理ランナーインターフェース
Definition: TnbThread.h:341
bool IsRunnable(void) const
[確認] 実行可能か否か
Definition: TnbThread.h:355
性能プロパティ型.
DWORD receiveTimeout
受信待ち時間。 INFINITE ならブロックされる。