#include "stdafx.h" #include "DppComm.h" #include CDppComm::CDppComm() { PortIDSetting = 0; PortIsOpen = FALSE; m_hDppComm = NULL; m_hWriteEvent = NULL; ghThreadExitEvent = NULL; m_szWriteBuffer = NULL; m_bThreadRunning = FALSE; osIO.Offset = 0; osIO.OffsetHigh = 0; osIO.hEvent = NULL; ExitEvent = FALSE; } // Delete dynamic memory CDppComm::~CDppComm() { if (PortIsOpen) { ExitEvent = TRUE; do { SetEvent(ghThreadExitEvent); } while (m_bThreadRunning); CloseHandle(ghThreadExitEvent); // close event handles CloseHandle(osIO.hEvent); CloseHandle(m_hWriteEvent); if (m_hDppComm != NULL) { CloseHandle(m_hDppComm); m_hDppComm = NULL; } } delete [] m_szWriteBuffer; PortIsOpen = FALSE; ExitEvent = FALSE; } BOOL CDppComm::Settings(CWnd* hPortWnd, UINT PortID, UINT BaudRate, char Parity, UINT DataBits, UINT StopBits, DWORD dwCommEvents, UINT WriteBuffSize) { if (m_bThreadRunning) { ExitEvent = TRUE; do { SetEvent(ghThreadExitEvent); } while (m_bThreadRunning); } ExitEvent = FALSE; // create events if (osIO.hEvent != NULL) ResetEvent(osIO.hEvent); osIO.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (ghThreadExitEvent != NULL) ResetEvent(ghThreadExitEvent); ghThreadExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // initialize the event objects m_hEvents[0] = ghThreadExitEvent; // highest priority m_hEvents[1] = osIO.hEvent; m_hEvents[2] = m_hWriteEvent; // initialize critical section InitializeCriticalSection(&m_csCommunicationSync); // set buffersize for writing and save the owner m_pOwner = hPortWnd; if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new unsigned char[WriteBuffSize]; m_nWriteBufferSize = WriteBuffSize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; char *szComPort = new char[50]; char *szSettings = new char[50]; EnterCriticalSection(&m_csCommunicationSync); if (m_hDppComm != NULL) { CloseHandle(m_hDppComm); m_hDppComm = NULL; } sprintf(szComPort, "\\\\.\\COM%d", PortID); sprintf(szSettings, "baud=%d parity=%c data=%d stop=%d", BaudRate, Parity, DataBits, StopBits); m_hDppComm = CreateFile(szComPort,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); if (m_hDppComm == INVALID_HANDLE_VALUE) { delete [] szComPort; delete [] szSettings; PortIDSetting = 0; return FALSE; } else { PortIDSetting = PortID; } m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; if (SetCommTimeouts(m_hDppComm, &m_CommTimeouts)) { if (SetCommMask(m_hDppComm, dwCommEvents)) { if (GetCommState(m_hDppComm, &m_dcb)) { m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! if (BuildCommDCB(szSettings, &m_dcb)) { if (SetCommState(m_hDppComm, &m_dcb)) { // running } else { GetCommErrStr("SetCommState()"); } } else { GetCommErrStr("BuildCommDCB()"); } } else { GetCommErrStr("GetCommState()"); } } else { GetCommErrStr("SetCommMask()"); } } else { GetCommErrStr("SetCommTimeouts()"); } delete [] szComPort; delete [] szSettings; PurgeComm(m_hDppComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); LeaveCriticalSection(&m_csCommunicationSync); return TRUE; } UINT CDppComm::DppCommThread(LPVOID pParam) { CDppComm *port = (CDppComm*)pParam; port->m_bThreadRunning = TRUE; DWORD BytesTransfered = 0; DWORD Event = 0; DWORD CommEvent = 0; DWORD dwError = 0; COMSTAT comStat; BOOL bResult = TRUE; comStat.cbInQue = 0; comStat.cbOutQue = 0; if (port->m_hDppComm){ PurgeComm(port->m_hDppComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); } for (;;) { //if (ExitEvent) TRACE("CDppComm::DppCommThread WaitCommEvent\n"); bResult = WaitCommEvent(port->m_hDppComm, &Event, &port->osIO); if (!bResult) { switch (dwError = GetLastError()) { case ERROR_IO_PENDING: { break; } case ERROR_INVALID_PARAMETER: { break; } default: { port->GetCommErrStr("WaitCommEvent()"); break; } } } else { bResult = ClearCommError(port->m_hDppComm, &dwError, &comStat); if (comStat.cbInQue == 0) continue; } //if (ExitEvent) TRACE("CDppComm::DppCommThread WaitForMultipleObjects\n"); Event = WaitForMultipleObjects(3, port->m_hEvents, FALSE, INFINITE); //if (ExitEvent) TRACE("CDppComm::DppCommThread Event %d\n",Event); switch (Event) { case EV_THREAD_EXIT_EVENT: // exit thread { if (port->m_hDppComm){ PurgeComm(port->m_hDppComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); SetCommMask(port->m_hDppComm, 0); } port->m_bThreadRunning = FALSE; AfxEndThread(100); break; } case EV_READ_STATUS_EVENT: // read byte data { GetCommMask(port->m_hDppComm, &CommEvent); if (CommEvent & EV_RXCHAR) { ReceiveByte(port, comStat); } break; } case EV_WRITE_DATA_EVENT: //write byte data { WriteByte(port); break; } } //if (ExitEvent) TRACE("CDppComm::DppCommThread Next\n"); } ////if (ExitEvent) { // quit if exiting thread //// AfxMessageBox("Exit Comm Thread"); ////} return 0; } BOOL CDppComm::OpenPort() { if (!(m_WinThread = AfxBeginThread(DppCommThread, this))) { PortIsOpen = FALSE; return FALSE; } else { PortIsOpen = TRUE; return TRUE; } } BOOL CDppComm::ClosePort() { UINT64 SetCount; SetCount=0; //TRACE("CDppComm::ClosePort\n"); ExitEvent = TRUE; do { SetEvent(ghThreadExitEvent); SetCount++; //TRACE("SetEvent(ghThreadExitEvent) %d\n",SetCount); if ((SetCount == 12) || (SetCount == 100)) { if (m_bThreadRunning) m_WinThread->PumpMessage(); //TRACE("CDppComm::ClosePort PumpMessage\n"); } } while (m_bThreadRunning); CloseHandle(ghThreadExitEvent); // close event handles CloseHandle(osIO.hEvent); CloseHandle(m_hWriteEvent); if (m_hDppComm != NULL) { CloseHandle(m_hDppComm); m_hDppComm = NULL; } PortIsOpen = FALSE; ExitEvent = FALSE; return TRUE; } void CDppComm::GetCommErrStr(char* ErrorText) { char *Temp = new char[200]; LPVOID lpMsgBuf; //if (ExitEvent) TRACE("CDppComm::GetCommErrStr\n"); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); sprintf(Temp, "DppComm %s Error: \n%s\n", (char*)ErrorText, lpMsgBuf); MessageBox(NULL, Temp, "DppComm Error", MB_ICONSTOP); LocalFree(lpMsgBuf); delete[] Temp; } void CDppComm::WriteByte(CDppComm* port) { BOOL bWrite = TRUE; BOOL bResult = TRUE; DWORD BytesSent = 0; //if (ExitEvent) TRACE("CDppComm::WriteByte\n"); ResetEvent(port->m_hWriteEvent); if (ExitEvent) { // quit if exiting thread return; } EnterCriticalSection(&port->m_csCommunicationSync); if (bWrite) { port->osIO.Offset = 0; port->osIO.OffsetHigh = 0; PurgeComm(port->m_hDppComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); bResult = WriteFile(port->m_hDppComm,port->m_szWriteBuffer,(DWORD)m_SendBytes,&BytesSent,&port->osIO); if (!bResult) { DWORD dwError = GetLastError(); switch (dwError) { case ERROR_IO_PENDING: { BytesSent = 0; bWrite = FALSE; break; } default: { port->GetCommErrStr("WriteFile()"); } } } else { LeaveCriticalSection(&port->m_csCommunicationSync); } } if (!bWrite) { bWrite = TRUE; bResult = GetOverlappedResult(port->m_hDppComm,&port->osIO,&BytesSent,TRUE); LeaveCriticalSection(&port->m_csCommunicationSync); if (!bResult) { port->GetCommErrStr("GetOverlappedResults() in WriteFile()"); } } if (BytesSent != m_SendBytes) { //AfxMessageBox("DppComm WriteByte Bytes Sent != Buffer Length %d != %d\n", BytesSent, m_SendBytes); } } void CDppComm::ReceiveByte(CDppComm* port, COMSTAT comStat) { BOOL bRead = TRUE; BOOL bResult = TRUE; DWORD dwError = 0; DWORD BytesRead = 0; unsigned char RXBuff; //if (ExitEvent) TRACE("CDppComm::ReceiveByte\n"); if (ExitEvent) { // quit if exiting thread return; } for (;;) { if (ExitEvent) { // quit if exiting thread break; } EnterCriticalSection(&port->m_csCommunicationSync); bResult = ClearCommError(port->m_hDppComm, &dwError, &comStat); LeaveCriticalSection(&port->m_csCommunicationSync); if (comStat.cbInQue == 0) { // que empty break; } EnterCriticalSection(&port->m_csCommunicationSync); if (bRead) { bResult = ReadFile(port->m_hDppComm,&RXBuff,1,&BytesRead,&port->osIO); if (!bResult) { // error switch (dwError = GetLastError()) { case ERROR_IO_PENDING: { bRead = FALSE; break; } default: { port->GetCommErrStr("ReadFile()"); break; } } } else { bRead = TRUE; } } if (!bRead) { bRead = TRUE; bResult = GetOverlappedResult(port->m_hDppComm,&port->osIO,&BytesRead,TRUE); if (!bResult) { // error port->GetCommErrStr("GetOverlappedResults() in ReadFile()"); } } LeaveCriticalSection(&port->m_csCommunicationSync); if (ExitEvent) { // quit if exiting thread break; } ::SendMessage((port->m_pOwner)->m_hWnd, WM_DPPCOMM_RCV_CHAR, (WPARAM) RXBuff, (LPARAM) BytesRead); // rcv byte if (ExitEvent) { // quit if exiting thread break; } } } void CDppComm::WriteData(unsigned char* string, size_t NumBytes) { //if (ExitEvent) TRACE("CDppComm::WriteData\n"); if (ExitEvent) { // quit if exiting thread return; } assert(m_hDppComm != 0); m_SendBytes = NumBytes; memset(m_szWriteBuffer, 0, m_SendBytes); for (size_t i=0; iWriteData(Buffer, PLen); return true; }