📄 ecostestserial.cpp
字号:
//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.//// This program is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//=================================================================//// eCosTestSerial.cpp//// Serial test class////=================================================================//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s): sdf// Contributors: sdf// Date: 1999-04-01// Description: This class abstracts the serial port for use in the testing infrastructure// Usage:////####DESCRIPTIONEND#####include "eCosStd.h"#include "eCosTestSerial.h"#include "eCosTrace.h"CeCosTestSerial::CeCosTestSerial(): m_nErr(0), m_pHandle(0), m_nDataBits(8), m_nStopBits(ONE_STOP_BIT), m_bParity(false), m_nBaud(0), m_nTotalReadTimeout(10*1000), m_nTotalWriteTimeout(10*1000), m_nInterCharReadTimeout(500), m_nInterCharWriteTimeout(500), m_bBlockingReads(true){}CeCosTestSerial::~CeCosTestSerial(){ Close();}CeCosTestSerial::CeCosTestSerial(LPCTSTR pszPort,int nBaud): m_nErr(0), m_pHandle(0), m_nDataBits(8), m_nStopBits(ONE_STOP_BIT), m_bParity(false), m_nTotalReadTimeout(10*1000), m_nTotalWriteTimeout(10*1000), m_nInterCharReadTimeout(500), m_nInterCharWriteTimeout(500), m_bBlockingReads(true){ Open(pszPort,nBaud);}bool CeCosTestSerial::SetBlockingReads(bool b,bool bApplySettingsNow/*=true*/){ m_bBlockingReads=b; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetBaud(unsigned int nBaud,bool bApplySettingsNow/*=true*/){ m_nBaud=nBaud; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetParity(bool bParityOn,bool bApplySettingsNow/*=true*/){ m_bParity=bParityOn; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetDataBits(int n,bool bApplySettingsNow/*=true*/){ m_nDataBits=n; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetStopBits(StopBitsType n,bool bApplySettingsNow/*=true*/){ m_nStopBits=n; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetReadTimeOuts(int nTotal,int nBetweenChars,bool bApplySettingsNow/*=true*/) // mSec{ m_nTotalReadTimeout=nTotal; m_nInterCharReadTimeout=nBetweenChars; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}bool CeCosTestSerial:: SetWriteTimeOuts(int nTotal,int nBetweenChars,bool bApplySettingsNow/*=true*/) // mSec{ m_nTotalWriteTimeout=nTotal; m_nInterCharWriteTimeout=nBetweenChars; return 0==m_pHandle || !bApplySettingsNow || ApplySettings();}/*bool CeCosTestSerial::Read (String &str){TCHAR *c=str.GetBuffer();unsigned int nRead=0;bool rc=Read(c,str.GetLength(),nRead);c[nRead]=_TCHAR('\0');str.ReleaseBuffer();return rc;} bool CeCosTestSerial::Write(const String &str) { unsigned int nWritten=0; return Write((void *)(LPCTSTR)str,str.GetLength(),nWritten) && nWritten==str.GetLength(); }*/#ifdef _WIN32bool CeCosTestSerial::Open(LPCTSTR pszPort,int nBaud){ bool rc=false; m_nBaud=nBaud, m_strPort=pszPort; HANDLE hCom=::CreateFile(pszPort,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL); SaveError(); if (INVALID_HANDLE_VALUE==hCom) { ERROR(_T("Failed to open port %s - %s\n"),pszPort,(LPCTSTR)ErrString()); } else { m_pHandle=(void *)hCom; if(ApplySettings()){ Flush(); rc=true; } else { Close(); } } return rc;}bool CeCosTestSerial::Close(){ bool rc=false; if(m_pHandle){ try { rc=(TRUE==CloseHandle((HANDLE)m_pHandle)); } catch(...) { TRACE(_T("!!! Exception caught closing serial handle %08x\n"),m_pHandle); } m_pHandle=0; } else { rc=true; } return rc;}bool CeCosTestSerial::ApplySettings(){ bool rc=false; try { DCB dcb; ZeroMemory(&dcb,sizeof dcb); dcb.DCBlength=sizeof dcb; dcb.BaudRate=m_nBaud; dcb.fBinary=true; dcb.fParity=true; dcb.Parity=(BYTE) ((m_bParity) ? EVENPARITY : NOPARITY); dcb.StopBits=(BYTE)m_nStopBits; dcb.ByteSize=(BYTE)m_nDataBits; LPCTSTR arpszStopbits[3]={_T("1"),_T("1.5"),_T("2")}; TRACE(_T("Applysettings baud=%d Parity=%d stopbits=%s databits=%d\n"), dcb.BaudRate, dcb.Parity, arpszStopbits[dcb.StopBits], dcb.ByteSize); // No control over the following yet dcb.fDtrControl=DTR_CONTROL_ENABLE; dcb.fTXContinueOnXoff=1; dcb.fRtsControl=RTS_CONTROL_ENABLE; dcb.fAbortOnError=1; dcb.XonLim=2048; dcb.XoffLim=512; dcb.XonChar=17; dcb.XoffChar=19; HANDLE hCom=(HANDLE)m_pHandle; if (!SetCommState(hCom, &dcb)) { SaveError(); ERROR(_T("Failed to set comm state - port %s handle=%d err=%d\n"),(LPCTSTR)m_strPort,hCom,GetLastError()); } else { COMMTIMEOUTS commtimeouts; if(m_bBlockingReads){ commtimeouts.ReadIntervalTimeout=m_nInterCharReadTimeout; commtimeouts.ReadTotalTimeoutMultiplier=0; commtimeouts.ReadTotalTimeoutConstant=m_nTotalReadTimeout; } else { commtimeouts.ReadIntervalTimeout=MAXDWORD; commtimeouts.ReadTotalTimeoutMultiplier=0; commtimeouts.ReadTotalTimeoutConstant=0; } commtimeouts.WriteTotalTimeoutMultiplier=m_nTotalWriteTimeout; commtimeouts.WriteTotalTimeoutConstant=m_nInterCharWriteTimeout; if (SetCommTimeouts(hCom, &commtimeouts)) { rc=true; } else { SaveError(); ERROR(_T("Failed to set comm timeouts - port %s\n"),(LPCTSTR)m_strPort); } } } catch(...) { TRACE(_T("!!! Exception caught in CeCosTestSerial::ApplySettings!!!\n")); } return rc;}bool CeCosTestSerial::Read (void *pBuf,unsigned int nSize,unsigned int &nRead){ bool rc=(TRUE==ReadFile((HANDLE)m_pHandle,pBuf,nSize,(LPDWORD)&nRead,0)); SaveError(); return rc;}bool CeCosTestSerial::Write(void *pBuf,unsigned int nSize,unsigned int &nWritten){ bool rc=(TRUE==WriteFile((HANDLE)m_pHandle,pBuf,nSize,(LPDWORD)&nWritten,0)); SaveError(); return rc;}bool CeCosTestSerial::ClearError(){ DWORD dwErrors; bool rc=(TRUE==ClearCommError(HANDLE(m_pHandle),&dwErrors,0)); if(dwErrors&CE_BREAK)TRACE(_T("The hardware detected a break condition.\n")); if(dwErrors&CE_DNS)TRACE(_T("Windows 95 and Windows 98: A parallel device is not selected.\n")); if(dwErrors&CE_FRAME)TRACE(_T("The hardware detected a framing error.\n")); if(dwErrors&CE_IOE)TRACE(_T("An I/O error occurred during communications with the device.\n")); if(dwErrors&CE_MODE)TRACE(_T("The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error.\n")); if(dwErrors&CE_OOP)TRACE(_T("Windows 95 and Windows 98: A parallel device signaled that it is out of paper.\n")); if(dwErrors&CE_OVERRUN)TRACE(_T("A character-buffer overrun has occurred. The next character is lost.\n")); if(dwErrors&CE_PTO)TRACE(_T("Windows 95 and Windows 98: A time-out occurred on a parallel device.\n")); if(dwErrors&CE_RXOVER)TRACE(_T("An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character.\n")); if(dwErrors&CE_RXPARITY)TRACE(_T("The hardware detected a parity error.\n")); if(dwErrors&CE_TXFULL)TRACE(_T("The application tried to transmit a character, but the output buffer was full.\n")); return rc;}bool CeCosTestSerial::Flush (void){ bool rc=(TRUE==PurgeComm ((HANDLE)m_pHandle,PURGE_TXCLEAR|PURGE_RXCLEAR)); SaveError(); return rc;}String CeCosTestSerial::ErrString(){ String str; LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_nErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); str=(LPCTSTR)lpMsgBuf; // Free the buffer. LocalFree( lpMsgBuf ); return str;}#else // UNIXString CeCosTestSerial::ErrString(){ return strerror(errno);}bool CeCosTestSerial::Close(){ bool rc=m_pHandle && (-1!=close((int)m_pHandle)); m_pHandle=0; return rc;}bool CeCosTestSerial::Open(LPCTSTR pszPort,int nBaud){ bool rc=false; m_nBaud=nBaud, m_strPort=pszPort; int fd = open(pszPort,O_RDWR|O_NONBLOCK); if (-1==fd) { ERROR(_T("Failed to open port %s\n"),pszPort); return false; } else { m_pHandle=(void *)fd; if(ApplySettings()){ rc=true; } else { Close(); ERROR(_T("Failed to apply settings.\n")); return false; } } return rc;}bool CeCosTestSerial::ApplySettings(){ struct termios buf, buf_verify; int rate; // Clear the two structures so we can make a binary comparison later on. memset(&buf, 0, sizeof(buf)); memset(&buf_verify, 0, sizeof(buf_verify)); LPCTSTR arpszStopbits[3]={_T("1"),_T("1.5"),_T("2")}; TRACE(_T("Applysettings baud=%d bParity=%d stopbits=%s databits=%d\n"), m_nBaud, m_bParity, arpszStopbits[m_nStopBits], m_nDataBits); switch(m_nBaud) { case 110: rate = B110; break; case 150: rate = B150; break; case 300: rate = B300; break; case 600: rate = B600; break; case 1200: rate = B1200; break; case 2400: rate = B2400; break; case 4800: rate = B4800; break; case 9600: rate = B9600; break; case 19200: rate = B19200; break; case 38400: rate = B38400; break; case 57600: rate = B57600; break; case 115200: rate = B115200; break; default: return false; }; TRACE(_T("Changing configuration...\n")); // Get current settings. if (tcgetattr((int) m_pHandle, &buf)) { fprintf(stderr, _T("Error: tcgetattr\n")); return false; } // Reset to raw. buf.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); buf.c_oflag &= ~OPOST; buf.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); buf.c_cflag &= ~(CSIZE|PARENB); buf.c_cflag |= CS8; // Set baud rate. cfsetispeed(&buf, rate); cfsetospeed(&buf, rate); // Set data bits. { int data_bits[9] = {0, 0, 0, 0, 0, CS5, CS6, CS7, CS8}; buf.c_cflag &= ~CSIZE; buf.c_cflag |= data_bits[m_nDataBits]; } // Set stop bits. { buf.c_cflag &= ~CSTOPB; if (ONE_STOP_BIT != m_nStopBits) buf.c_cflag |= CSTOPB; } // Set parity. { buf.c_cflag &= ~(PARENB | PARODD); // no parity. if (m_bParity) // even parity. buf.c_cflag |= PARENB; } // Set the new settings if (tcsetattr((int) m_pHandle, TCSADRAIN, &buf)) { fprintf(stderr, _T("Error: tcsetattr\n")); return false; } // Now read back the settings. On SunOS tcsetattr only returns // error if _all_ settings fail. If just a few settings are not // supported, the call returns true while the hardware is set to a // combination of old and new settings. if (tcgetattr((int) m_pHandle, &buf_verify)) { fprintf(stderr, _T("Error: tcgetattr\n")); return false; } if (memcmp(&buf, &buf_verify, sizeof(buf))) { fprintf(stderr, _T("Error: termios verify failed\n")); return false; } // A slight delay to allow things to settle. Sleep(10); TRACE(_T("Done.\n")); return true;}bool CeCosTestSerial::Flush (void){ return 0==tcflush((int) m_pHandle, TCIOFLUSH);}bool CeCosTestSerial::Read (void *pBuf,unsigned int nSize,unsigned int &nRead){ if (!m_bBlockingReads) { nRead = 0; int n = read((int)m_pHandle, pBuf, nSize); if (-1 == n) { if (EAGAIN == errno) return true; ERROR(_T("Read failed: %d\n"), errno); return false; } nRead = n; return true; } // Blocking reads: emulate the Windows semantics: // If m_nTotalReadTimeout elapses before we see the first TCHAR, // return. // If m_nInterCharReadTimeout elapses after reading any // subsequent TCHAR, return. fd_set rfds; FD_ZERO(&rfds); FD_SET((int)m_pHandle, &rfds); // Start with total timeout. struct timeval tv; tv.tv_sec = m_nTotalReadTimeout / 1000; tv.tv_usec = (m_nTotalReadTimeout % 1000) * 1000; unsigned char* pData = (unsigned char*) pBuf; nRead = 0; while (nSize) { switch(select((int)m_pHandle + 1, &rfds, NULL, NULL, &tv)) { case 1: { int n = read((int)m_pHandle, pData, nSize); if (-1 == n && EAGAIN != errno) { ERROR(_T("Read failed: %d\n"), errno); return false; // FAILED } nRead += n; pData += n; nSize -= n; // Now use inter-char timeout. tv.tv_sec = m_nInterCharReadTimeout / 1000; tv.tv_usec = (m_nInterCharReadTimeout % 1000) * 1000; } break; case 0: return true; // Timeout case -1: ERROR(_T("Select failed: %d\n"), errno); return false; } } return true;}bool CeCosTestSerial::Write(void *pBuf,unsigned int nSize,unsigned int &nWritten){ bool rc; int n=write((int)m_pHandle,pBuf,nSize); if(-1==n){ nWritten=0; if (errno == EAGAIN) rc = true; else rc=false; } else { nWritten=n; rc=true; } return rc;}bool CeCosTestSerial::ClearError(){ return false;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -