// Stop Rx Thread // return: TRUE on success, FALSE on error BOOL ComPort::StopRxThread() { if (hPort == INVALID_HANDLE_VALUE) return FALSE; if (fRxThreadTerminated) return TRUE; CloseThread = TRUE; // currently NEWCOMM is NOT used #if (WINDOWSPC>0) || NEWCOMM // 091206 DWORD tm = GetTickCount()+20000l; while (!fRxThreadTerminated && ((tm-GetTickCount()) > 0) ) { Sleep(10); } if (!fRxThreadTerminated) { TerminateThread(hReadThread, 0); } else { CloseHandle(hReadThread); } #else Flush(); // setting the comm event mask with the same value // GetCommMask(hPort, &dwMask); SetCommMask(hPort, dwMask); // will cancel any // WaitCommEvent! this is a // documented CE trick to // cancel the WaitCommEvent int count=0; while (!fRxThreadTerminated && (count<2000)){ Sleep(10); count++; } if (!fRxThreadTerminated) { #if 101122 TerminateThread(hReadThread, 0); StartupStore(_T("...... ComPort StopRxThread: RX Thread forced to terminate!%s"),NEWLINE); #else // LKTOKEN _@M540_ = "RX Thread not Terminated!" ComPort_StatusMessage(MB_OK, TEXT("Error"), TEXT("%s %s"), sPortName, gettext(TEXT("_@M540_"))); StartupStore(_T("...... ComPort %d StopRxThread: RX Thread not terminated!%s"),sportnumber+1,NEWLINE); #endif //#endif } else { CloseHandle(hReadThread); StartupStore(_T(". ComPort %d StopRxThread: RX Thread terminated%s"),sportnumber+1,NEWLINE); } #endif return fRxThreadTerminated; }
// Set Rx Timeout in ms // Timeout: Rx receive timeout in ms // return: last set Rx timeout or -1 on error int ComPort::SetRxTimeout(int Timeout) { COMMTIMEOUTS CommTimeouts; int result; DWORD dwError; if (hPort == INVALID_HANDLE_VALUE) return -1; GetCommTimeouts(hPort, &CommTimeouts); result = CommTimeouts.ReadTotalTimeoutConstant; // Change the COMMTIMEOUTS structure settings. CommTimeouts.ReadIntervalTimeout = MAXDWORD; // JMW 20070515 if (Timeout == 0) { // no total timeouts used CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; } else { // only total timeout used CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD; CommTimeouts.ReadTotalTimeoutConstant = Timeout; } CommTimeouts.WriteTotalTimeoutMultiplier = 10; CommTimeouts.WriteTotalTimeoutConstant = 1000; // Set the time-out parameters // for all read and write // operations on the port. if (!SetCommTimeouts(hPort, &CommTimeouts)) { // Could not create the read thread. CloseHandle(hPort); hPort = INVALID_HANDLE_VALUE; #if (WINDOWSPC>0) || NEWCOMM // 091206 Sleep(2000); // needed for windows bug #endif ComPort_StatusMessage(MB_OK, TEXT("Error"), TEXT("%s %s"), // LKTOKEN _@M760_ = "Unable to Set Serial Port Timers" gettext(TEXT("_@M760_")), sPortName); dwError = GetLastError(); return -1; } return result; }
// Restart Rx Thread // return: TRUE on success, FALSE on error BOOL ComPort::StartRxThread(void) { DWORD dwThreadID, dwError; if (hPort == INVALID_HANDLE_VALUE) return FALSE; CloseThread = FALSE; // Create a read thread for reading data from the communication port. if ((hReadThread = CreateThread (NULL, 0, ThreadProc, this, 0, &dwThreadID)) != NULL) { SetThreadPriority(hReadThread, THREAD_PRIORITY_NORMAL); //THREAD_PRIORITY_ABOVE_NORMAL //???? JMW Why close it here? CloseHandle(hReadThread); } else { // Could not create the read thread. // LKTOKEN _@M761_ = "Unable to Start RX Thread on Port" ComPort_StatusMessage(MB_OK, TEXT("Error"), TEXT("%s %s"), gettext(TEXT("_@M761_")), sPortName); dwError = GetLastError(); return FALSE; } return TRUE; }
// Initialize is called from device devInit, and dwPortNumber is passed along new threads BOOL ComPort::Initialize(LPCTSTR lpszPortName, DWORD dwPortSpeed, DWORD dwPortBit, DWORD dwPortNumber) { DWORD dwError; DCB PortDCB; TCHAR lkbuf[100]; TCHAR lkPortName[10]; // 9 should be enough if (SIMMODE) return FALSE; #if (WINDOWSPC>0) // Do not use anymore COMn: , use \\.\COMnn on PC version if (lpszPortName) { _tcscpy(sPortName,_T("\\\\.\\")); // 091117 _tcscat(sPortName, lpszPortName); _tcscpy(lkPortName, lpszPortName); } #else if (lpszPortName) { _tcscpy(sPortName, lpszPortName); _tcscpy(lkPortName, lpszPortName); } #endif StartupStore(_T(". ComPort %u Initialize <%s> speed=%u bit=%u %s"),dwPortNumber+1,lkPortName,dwPortSpeed,8-dwPortBit,NEWLINE); hPort = CreateFile(sPortName, // Pointer to the name of the port GENERIC_READ | GENERIC_WRITE, // Access (read-write) mode 0, // Share mode NULL, // Pointer to the security attribute OPEN_EXISTING,// How to open the serial port FILE_ATTRIBUTE_NORMAL, // Port attributes NULL); // Handle to port with attribute // to copy if (hPort == INVALID_HANDLE_VALUE) { dwError = GetLastError(); _stprintf(lkbuf,_T("... ComPort %u Init failed, error=%u%s"),dwPortNumber+1,dwError,NEWLINE); // 091117 StartupStore(lkbuf); // LKTOKEN _@M762_ = "Unable to open port" ComPort_StatusMessage(MB_OK|MB_ICONINFORMATION, NULL, TEXT("%s %s"), gettext(TEXT("_@M762_")), lkPortName); return FALSE; } StartupStore(_T(". ComPort %u <%s> is now open%s"),dwPortNumber+1,lkPortName,NEWLINE); PortDCB.DCBlength = sizeof(DCB); // Get the default port setting information. if (GetCommState(hPort, &PortDCB)==0) { dwError = GetLastError(); _stprintf(lkbuf,_T("... ComPort %u GetCommState failed, error=%u%s"),dwPortNumber+1,dwError,NEWLINE); StartupStore(lkbuf); // cannot set serial port timers. good anyway ComPort_StatusMessage(MB_OK|MB_ICONINFORMATION, NULL, TEXT("%s %s"), gettext(TEXT("_@M760_")), lkPortName); return FALSE; } // Change the DCB structure settings. PortDCB.BaudRate = dwPortSpeed; // Current baud PortDCB.fBinary = TRUE; // Binary mode; no EOF check PortDCB.fParity = TRUE; // Enable parity checking PortDCB.fOutxCtsFlow = FALSE; // CTS output flow control: when TRUE, and CTS off, output suspended PortDCB.fOutxDsrFlow = FALSE; // DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx PortDCB.fOutX = FALSE; // No XON/XOFF out flow control PortDCB.fInX = FALSE; // No XON/XOFF in flow control PortDCB.fErrorChar = FALSE; // Disable error replacement PortDCB.fNull = FALSE; // Disable null removal PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control PortDCB.fAbortOnError = TRUE; // FALSE need something else to work switch(dwPortBit) { case bit7E1: PortDCB.ByteSize = 7; PortDCB.Parity = EVENPARITY; break; case bit8N1: default: PortDCB.ByteSize = 8; PortDCB.Parity = NOPARITY; break; } PortDCB.StopBits = ONESTOPBIT; PortDCB.EvtChar = '\n'; // wait for end of line, RXFLAG should detect it if (!SetCommState(hPort, &PortDCB)) { // Could not create the read thread. CloseHandle(hPort); hPort = INVALID_HANDLE_VALUE; #if (WINDOWSPC>0) || NEWCOMM // 091206 Sleep(2000); // needed for windows bug 101116 not verified #endif #if !(WINDOWSPC>0) if (PollingMode) Sleep(2000); #endif // LKTOKEN _@M759_ = "Unable to Change Settings on Port" ComPort_StatusMessage(MB_OK, TEXT("Error"), TEXT("%s %s"), gettext(TEXT("_@M759_")), lkPortName); dwError = GetLastError(); _stprintf(lkbuf,_T("... ComPort %u Init <%s> change setting FAILED, error=%u%s"),dwPortNumber+1,lkPortName,dwError,NEWLINE); // 091117 StartupStore(lkbuf); return FALSE; } SetRxTimeout(RXTIMEOUT); SetupComm(hPort, 1024, 1024); // Direct the port to perform extended functions SETDTR and SETRTS // SETDTR: Sends the DTR (data-terminal-ready) signal. // SETRTS: Sends the RTS (request-to-send) signal. EscapeCommFunction(hPort, SETDTR); EscapeCommFunction(hPort, SETRTS); sportnumber=dwPortNumber; // 100210 if (!StartRxThread()){ _stprintf(lkbuf,_T("... ComPort %u Init <%s> StartRxThread failed%s"),dwPortNumber+1,lkPortName,NEWLINE); StartupStore(lkbuf); if (!CloseHandle(hPort)) { dwError = GetLastError(); _stprintf(lkbuf,_T("... ComPort %u Init <%s> close failed, error=%u%s"),dwPortNumber+1,lkPortName,dwError,NEWLINE); StartupStore(lkbuf); } else { _stprintf(lkbuf,_T("... ComPort %u Init <%s> closed%s"),dwPortNumber+1,lkPortName,NEWLINE); StartupStore(lkbuf); } hPort = INVALID_HANDLE_VALUE; #if (WINDOWSPC>0) || NEWCOMM // 091206 Sleep(2000); // needed for windows bug #endif #if !(WINDOWSPC>0) if (PollingMode) Sleep(2000); #endif return FALSE; } _stprintf(lkbuf,_T(". ComPort %u Init <%s> end OK%s"),dwPortNumber+1,lkPortName,NEWLINE); StartupStore(lkbuf); return TRUE; }