14 #include "serial device.h" 15 #include "named pipes.h" 16 #include "misc tools.h" 20 BOOL (WINAPI *lpf_CancelIoEx)(HANDLE hFile, LPOVERLAPPED lpOverlapped)= NULL;
21 BOOL (WINAPI *lpf_CancelIo)(HANDLE hFile)= NULL;
26 DWORD WINAPI SerialProc(LPVOID lpParameter)
34 CManagerSerial::CManagerSerial(
CComm* pcComm,
const TCHAR szPipe[],
int nChan,
int &nError) :
35 CManager(SERIAL_MAN_STR, std::tstring(szPipe), nChan)
44 if (!pcComm || !szPipe)
46 nError= BAD_INPUT_PARAMS;
49 m_hLib= LoadLibrary(_T(
"kernel32.dll"));
52 nError= LIBRARY_ERROR;
55 *(FARPROC*)&lpf_CancelIoEx= GetProcAddress(m_hLib, _T(
"CancelIoEx"));
56 *(FARPROC*)&lpf_CancelIo= GetProcAddress(m_hLib, _T(
"CancelIo"));
57 if (!lpf_CancelIoEx && !lpf_CancelIo)
59 nError= LIBRARY_ERROR;
75 ((
SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
76 ((
SBaseOut*)pHead)->sBaseIn.nChan= m_nChan;
77 ((
SBaseOut*)pHead)->sBaseIn.nError= 0;
79 _tcsncpy_s(((
SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE,
m_csName.c_str(), _TRUNCATE);
84 CManagerSerial::~CManagerSerial()
86 for (
size_t i= 0; i<m_acSerialDevices.size(); ++i)
87 delete m_acSerialDevices[i];
106 if (!pHead || dwSize <
sizeof(
SBaseIn) || dwSize != ((
SBaseIn*)pHead)->dwSize)
108 sBase.nError= SIZE_MISSMATCH;
109 }
else if (((
SBaseIn*)pHead)->eType == eQuery && dwSize ==
sizeof(
SBaseIn))
112 if (((
SBaseIn*)pHead)->nChan < 0 || ((
SBaseIn*)pHead)->nChan >= m_acSerialDevices.size() ||
113 !m_acSerialDevices[((
SBaseIn*)pHead)->nChan])
115 sBase.nError= INVALID_CHANN;
119 DWORD dwSizeInfo= m_acSerialDevices[((
SBaseIn*)pHead)->nChan]->GetInfo(NULL, 0);
120 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(dwSizeInfo);
123 m_acSerialDevices[((
SBaseIn*)pHead)->nChan]->GetInfo(pBase, dwSizeInfo);
124 sData.dwSize= dwSizeInfo;
129 }
else if (dwSize ==
sizeof(
SBaseIn) && ((
SBaseIn*)pHead)->eType == eDelete)
131 sBase.eType= eDelete;
132 if (((
SBaseIn*)pHead)->nChan < 0 || ((
SBaseIn*)pHead)->nChan >= m_acSerialDevices.size() ||
133 !m_acSerialDevices[((
SBaseIn*)pHead)->nChan])
134 sBase.nError= INVALID_CHANN;
137 delete m_acSerialDevices[((
SBaseIn*)pHead)->nChan];
138 m_acSerialDevices[((
SBaseIn*)pHead)->nChan]= NULL;
139 sBase.nChan= ((
SBaseIn*)pHead)->nChan;
141 }
else if (dwSize ==
sizeof(
SBaseIn) && ((
SBaseIn*)pHead)->eType == eVersion &&
142 ((
SBaseIn*)pHead)->nChan == -1)
145 sBase.dwInfo= GetVersion();
146 sBase.eType= eVersion;
147 }
else if (((
SBaseIn*)pHead)->eType == eSet &&
149 ((
SBase*)((
char*)pHead+
sizeof(
SBaseIn)))->eType == eSerialChanInit)
152 LARGE_INTEGER llStart;
156 for (i = 0; i<m_acSerialDevices.size(); ++i)
158 if (m_acSerialDevices[i] && _tcscmp(m_acSerialDevices[i]->m_sChanInit.szPortName, sChanInit.szPortName) == 0)
160 sBase.nChan = (int)i;
161 sBase.nError = ALREADY_OPEN;
167 for (i = 0; i<m_acSerialDevices.size() && m_acSerialDevices[i]; ++i);
168 if (i == m_acSerialDevices.size())
169 m_acSerialDevices.push_back(NULL);
171 std::tstringstream ss;
173 std::tstringstream ss2;
175 std::tstring csPipeName= m_csPipeName+_T(
":")+ss2.str()+_T(
":")+ss.str();
179 m_acSerialDevices[i]= pcChan;
183 pBaseO->sBaseIn.dwSize=
sizeof(
SBaseOut);
184 pBaseO->sBaseIn.eType= eResponseExL;
185 pBaseO->sBaseIn.nChan= (int)i;
186 pBaseO->sBaseIn.nError= 0;
187 pBaseO->llLargeInteger= llStart;
188 pBaseO->bActive=
true;
190 sData.dwSize= pBaseO->sBaseIn.dwSize;
197 sBase.nError= INVALID_COMMAND;
199 if (sBase.nError || bRes)
205 memcpy(sData.pHead, &sBase,
sizeof(
SBaseIn));
215 LARGE_INTEGER &llStart) :
CDevice(SERIAL_CHAN_STR), m_csPipeName(szPipe),
216 m_sChanInit(sChanInit), m_usChan(nChan), m_hWriteEvent(CreateEvent(NULL,TRUE, FALSE, NULL)),
217 m_asWPackets(m_hWriteEvent), m_hReadEvent(CreateEvent(NULL,TRUE, FALSE, NULL)),
218 m_asRPackets(m_hReadEvent)
224 m_acReadBuffer= NULL;
227 memset(&m_sWOverlapped, 0,
sizeof(OVERLAPPED));
228 memset(&m_sROverlapped, 0,
sizeof(OVERLAPPED));
231 if (!szPipe || m_sChanInit.ucByteSize < 4 || m_sChanInit.ucByteSize > 8 ||
232 m_sChanInit.ucParity > 4 || m_sChanInit.ucStopBits > 2 ||
233 (!m_sChanInit.dwMaxStrRead && !m_sChanInit.dwMaxStrWrite))
235 nError= BAD_INPUT_PARAMS;
238 m_hStopEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
239 m_sWOverlapped.hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
240 m_sROverlapped.hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
241 m_acReadBuffer= (
char*)m_pcMemPool->PoolAcquire(
sizeof(
char)*m_sChanInit.dwMaxStrRead);
242 if (!m_hStopEvent || !m_hWriteEvent || !m_hReadEvent ||
243 !m_sWOverlapped.hEvent || !m_sROverlapped.hEvent || !m_acReadBuffer)
245 nError= NO_SYS_RESOURCE;
249 std::tstring csName= m_sChanInit.szPortName;
250 csName=
"\\\\.\\"+csName;
252 m_hPort= CreateFile(csName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
253 if (m_hPort == INVALID_HANDLE_VALUE || !m_hPort)
255 nError= WIN_ERROR(GetLastError(), nError);
259 memset(&sDcb, 0,
sizeof(DCB));
260 sDcb.DCBlength=
sizeof(DCB);
261 if (!GetCommState(m_hPort, &sDcb))
263 nError= WIN_ERROR(GetLastError(), nError);
266 sDcb.BaudRate= m_sChanInit.dwBaudRate;
267 sDcb.Parity= m_sChanInit.ucParity;
268 sDcb.ByteSize= m_sChanInit.ucByteSize;
269 sDcb.StopBits= m_sChanInit.ucStopBits;
270 sDcb.fRtsControl= RTS_CONTROL_DISABLE;
271 sDcb.fDtrControl= DTR_CONTROL_DISABLE;
278 if (!SetCommState(m_hPort, &sDcb))
280 nError= WIN_ERROR(GetLastError(), nError);
283 if (!SetCommMask(m_hPort, EV_RXCHAR))
285 nError= WIN_ERROR(GetLastError(), nError);
288 if (!GetCommTimeouts(m_hPort, &m_sTimeouts))
290 nError= WIN_ERROR(GetLastError(), nError);
293 COMMTIMEOUTS sTimeouts;
294 sTimeouts.ReadIntervalTimeout = MAXDWORD;
295 sTimeouts.ReadTotalTimeoutMultiplier = 0;
296 sTimeouts.ReadTotalTimeoutConstant = 0;
297 sTimeouts.WriteTotalTimeoutMultiplier = 0;
298 sTimeouts.WriteTotalTimeoutConstant = 0;
299 if (!SetCommTimeouts(m_hPort, &sTimeouts))
301 nError= WIN_ERROR(GetLastError(), nError);
306 nError=
static_cast<CPipeServer*
>(m_pcComm)->Init(szPipe, ~0x80000000, MIN_BUFF_IN+m_sChanInit.dwMaxStrWrite+
311 m_hThread= CreateThread(NULL, 0, SerialProc,
this, 0, NULL);
314 nError= NO_SYS_RESOURCE;
329 ((
SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
330 ((
SBaseOut*)pHead)->sBaseIn.nChan= m_usChan;
331 ((
SBaseOut*)pHead)->sBaseIn.nError= 0;
333 _tcsncpy_s(((
SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE,
m_csName.c_str(), _TRUNCATE);
334 pHead= (
char*)pHead+
sizeof(
SBaseOut);
337 ((
SBaseOut*)pHead)->sBaseIn.eType = eResponseExL;
338 ((
SBaseOut*)pHead)->sBaseIn.nChan = m_usChan;
339 ((
SBaseOut*)pHead)->sBaseIn.nError = 0;
342 pHead = (
char*)pHead +
sizeof(
SBaseOut);
345 ((
SBase*)pHead)->eType= eSerialChanInit;
346 pHead= (
char*)pHead+
sizeof(
SBase);
352 CChannelSerial::~CChannelSerial()
354 if (m_hThread && (WAIT_OBJECT_0 != SignalObjectAndWait(m_hStopEvent, m_hThread, 2000, FALSE)))
355 TerminateThread(m_hThread, 0);
356 if (m_hThread) CloseHandle(m_hThread);
357 if (m_hPort) PurgeComm(m_hPort, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
358 if (m_hPort) SetCommTimeouts(m_hPort, &m_sTimeouts);
359 if (m_hPort) CloseHandle(m_hPort);
360 if (m_pcComm) m_pcComm->
Close();
365 psPackt= m_asRPackets.
Front(
true, bValid);
366 if (psPackt && bValid)
368 m_pcMemPool->PoolRelease(psPackt->psSerialData);
374 psPackt= m_asWPackets.
Front(
true, bValid);
375 if (psPackt && bValid)
377 m_pcMemPool->PoolRelease(psPackt->psSerialData);
381 if (m_sROverlapped.hEvent) CloseHandle(m_sROverlapped.hEvent);
382 if (m_sWOverlapped.hEvent) CloseHandle(m_sWOverlapped.hEvent);
383 if (m_hStopEvent) CloseHandle(m_hStopEvent);
384 if (m_hWriteEvent) CloseHandle(m_hWriteEvent);
385 if (m_hReadEvent) CloseHandle(m_hReadEvent);
386 m_pcMemPool->PoolRelease(m_acReadBuffer);
397 if (!pBase || dwSize <
sizeof(
SBaseIn) || dwSize != pBase->dwSize)
398 nError= SIZE_MISSMATCH;
399 else if (pBase->nChan != m_usChan)
400 nError= INVALID_CHANN;
401 else if (!(dwSize ==
sizeof(
SBaseIn) && pBase->eType == eQuery) &&
402 !(pBase->eType == eData &&
403 ((
SBase*)((
char*)pBase+
sizeof(
SBaseIn)))->eType == eSerialWriteData &&
406 !(pBase->eType == eTrigger &&
407 ((
SBase*)((
char*)pBase+
sizeof(
SBaseIn)))->eType == eSerialReadData &&
409 nError= INVALID_COMMAND;
410 else if ((pBase->eType == eTrigger &&
413 (pBase->eType == eData &&
416 nError= BAD_INPUT_PARAMS;
423 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(sData.dwSize);
426 pBase->dwSize=
sizeof(
SBaseIn);
427 pBase->eType= eResponse;
429 pBase->nError= nError;
433 }
else if (pBase->eType == eQuery)
435 sData.dwSize=
GetInfo(NULL, 0);
436 sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
437 if (sData.pHead &&
GetInfo(sData.pHead, sData.dwSize) == sData.dwSize)
442 psPacket->psSerialData= (
SBase*)m_pcMemPool->PoolAcquire(dwSize-
sizeof(
SBaseIn));
443 if (psPacket->psSerialData)
445 memcpy(psPacket->psSerialData, (
char*)pHead+
sizeof(
SBaseIn), dwSize-
sizeof(
SBaseIn));
446 psPacket->llId= llId;
447 if (pBase->eType == eTrigger)
448 m_asRPackets.
Push(psPacket);
450 m_asWPackets.
Push(psPacket);
455 DWORD CChannelSerial::ThreadProc()
457 HANDLE ahEvents[]= {m_hStopEvent, m_hWriteEvent, m_hReadEvent, m_sWOverlapped.hEvent, m_sROverlapped.hEvent};
458 DWORD dwToRead= 0, dwRead= 0, dwToWrite= 0, dwWrote= 0, dwError, dwWait= INFINITE, dwMask= 0;
459 double dWStart, dRStart, dWDur= 0, dRDur= 0, dCurrTime;
460 bool bDone=
false, bValid, bWClear=
false, bRClear=
false, bRPending=
false;
464 memset(&sBaseOut, 0,
sizeof(
SBaseOut));
465 sBaseOut.bActive=
true;
466 sBaseOut.sBaseIn.eType= eResponseExD;
467 sBaseOut.sBaseIn.nChan= m_usChan;
473 switch (WaitForMultipleObjects(
sizeof(ahEvents)/
sizeof(HANDLE), &ahEvents[0], FALSE, dwWait))
475 case WAIT_OBJECT_0+1:
478 ResetEvent(m_hWriteEvent);
479 sPacket= m_asWPackets.
Front(
false, bValid);
480 if (!sPacket || !bValid)
482 dwToWrite= ((
SSerialData*)((
char*)sPacket->psSerialData+
sizeof(
SBase)))->dwSize;
483 if (!WriteFile(m_hPort, (
char*)sPacket->psSerialData+
sizeof(
SBase)+
sizeof(
SSerialData),
484 dwToWrite, &dwWrote, &m_sWOverlapped))
486 if ((dwError= GetLastError()) != ERROR_IO_PENDING)
487 sBaseOut.sBaseIn.nError= WIN_ERROR(dwError, sBaseOut.sBaseIn.nError);
491 dWDur= (double)((
SSerialData*)((
char*)sPacket->psSerialData+
sizeof(
SBase)))->dwTimeout/1000.0;
496 if (dwToWrite != dwWrote)
497 sBaseOut.sBaseIn.nError= RW_FAILED;
501 case WAIT_OBJECT_0+3:
504 ResetEvent(m_sWOverlapped.hEvent);
505 sPacket= m_asWPackets.
Front(
false, bValid);
506 if (!sPacket || !bValid)
508 if (GetOverlappedResult(m_hPort, &m_sWOverlapped, &dwWrote, FALSE))
510 if (dwToWrite != dwWrote)
511 sBaseOut.sBaseIn.nError= RW_FAILED;
514 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
517 case WAIT_OBJECT_0+2:
520 ResetEvent(m_hReadEvent);
521 sPacket= m_asRPackets.
Front(
false, bValid);
522 if (!sPacket || !bValid)
525 if (!WaitCommEvent(m_hPort, &dwMask, &m_sROverlapped))
527 dwError= GetLastError();
528 if (dwError != ERROR_IO_PENDING)
530 sBaseOut.sBaseIn.nError= WIN_ERROR(dwError, sBaseOut.sBaseIn.nError);
535 SetEvent(m_sROverlapped.hEvent);
536 dRDur= ((
SSerialData*)((
char*)sPacket->psSerialData+
sizeof(
SBase)))->dwTimeout/1000.0;
541 case WAIT_OBJECT_0+4:
544 ResetEvent(m_sROverlapped.hEvent);
545 sPacket= m_asRPackets.
Front(
false, bValid);
546 if (!sPacket || !bValid)
548 if (bRPending && !GetOverlappedResult(m_hPort, &m_sROverlapped, &dwError, FALSE))
550 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
554 if (!ClearCommError(m_hPort, &dwError, &m_sComStat))
556 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
559 if (bRPending && !(dwMask&EV_RXCHAR))
561 sBaseOut.sBaseIn.nError= RW_FAILED;
565 if (!ReadFile(m_hPort, &m_acReadBuffer[nPos], min(m_sComStat.cbInQue,
567 &dwRead, &m_sROverlapped))
569 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
572 bool bCompleted=
false;
576 for (; i<nPos+(int)dwRead && (m_acReadBuffer[i]!=((
SSerialData*)((
char*)sPacket->psSerialData+
sizeof(
SBase)))->cStop);++i);
577 bCompleted= i<nPos+(int)dwRead;
579 bCompleted= nPos+dwRead == ((
SSerialData*)((
char*)sPacket->psSerialData+
sizeof(
SBase)))->dwSize;
583 sBaseOut.sBaseIn.nError= RW_FAILED;
589 if (!WaitCommEvent(m_hPort, &dwMask,&m_sROverlapped))
591 dwError= GetLastError();
592 if (dwError != ERROR_IO_PENDING)
594 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
599 if (!ClearCommError(m_hPort, &dwError, &m_sComStat))
601 sBaseOut.sBaseIn.nError= WIN_ERROR(GetLastError(), sBaseOut.sBaseIn.nError);
606 sBaseOut.sBaseIn.nError= RW_FAILED;
609 if (m_sComStat.cbInQue)
610 SetEvent(m_sROverlapped.hEvent);
614 SetEvent(m_sROverlapped.hEvent);
624 if (dWDur && dCurrTime > dWDur+dWStart)
625 lpf_CancelIoEx(m_hPort, &m_sWOverlapped);
626 if (dRDur && dCurrTime > dRDur+dRStart)
627 lpf_CancelIoEx(m_hPort, &m_sROverlapped);
628 }
else if (lpf_CancelIo)
630 if (dWDur && dCurrTime > dWDur+dWStart)
631 lpf_CancelIo(m_hPort);
632 if (dRDur && dCurrTime > dRDur+dRStart)
633 lpf_CancelIo(m_hPort);
645 sPacket= m_asRPackets.
Front(
true, bValid);
647 SetEvent(m_hReadEvent);
648 if (sPacket && bValid)
650 sBaseOut.dDouble= g_cTimer.
Seconds();
652 sBaseOut.sBaseIn.dwSize= sData.dwSize;
657 memcpy(pBase, &sBaseOut,
sizeof(
SBaseOut));
659 ((
SBase*)((
char*)pBase+
sizeof(
SBaseOut)))->eType= eSerialReadData;
662 m_pcComm->
SendData(&sData, sPacket->llId);
664 m_pcMemPool->PoolRelease(sPacket->psSerialData);
674 sPacket= m_asWPackets.
Front(
true, bValid);
676 SetEvent(m_hWriteEvent);
677 if (sPacket && bValid)
679 sBaseOut.dDouble= g_cTimer.
Seconds();
681 sBaseOut.sBaseIn.dwSize= sData.dwSize;
686 memcpy(pBase, &sBaseOut,
sizeof(
SBaseOut));
688 ((
SBase*)((
char*)pBase+
sizeof(
SBaseOut)))->eType= eSerialWriteData;
690 m_pcComm->
SendData(&sData, sPacket->llId);
692 m_pcMemPool->PoolRelease(sPacket->psSerialData);
699 sBaseOut.sBaseIn.nError= 0;
703 dwWait= (DWORD)((dWDur-(dCurrTime-dWStart))<0.004?4:ceil(1000*(dWDur-(dCurrTime-dWStart))));
705 dwWait= (DWORD)min((dRDur-(dCurrTime-dRStart))<0.004?4:ceil(1000*(dRDur-(dCurrTime-dRStart))), dwWait);
708 sBaseOut.sBaseIn.dwSize=
sizeof(
SBaseIn);
709 sBaseOut.sBaseIn.eType= eResponse;
710 sBaseOut.sBaseIn.nError= DEVICE_CLOSING;
714 sPacket= m_asRPackets.
Front(
true, bValid);
715 if (!sPacket || !bValid)
717 sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
720 memcpy(sData.pHead, &sBaseOut.sBaseIn, sData.dwSize);
721 m_pcComm->
SendData(&sData, sPacket->llId);
723 m_pcMemPool->PoolRelease(sPacket->psSerialData);
728 sPacket= m_asWPackets.
Front(
true, bValid);
729 if (!sPacket || !bValid)
731 sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
734 memcpy(sData.pHead, &sBaseOut.sBaseIn, sData.dwSize);
735 m_pcComm->
SendData(&sData, sPacket->llId);
737 m_pcMemPool->PoolRelease(sPacket->psSerialData);
DWORD GetInfo(void *pHead, DWORD dwSize)
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
virtual int SendData(const SData *pData, __int64 llId)=0
virtual DWORD GetInfo(void *pHead, DWORD dwSize)
LARGE_INTEGER GetStart() const
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
const std::tstring m_csName
T Front(bool bPop, bool &bValid)
CChannelSerial(const TCHAR szPipe[], int nChan, SChanInitSerial &sChanInit, int &nError, LARGE_INTEGER &llStart)