#ifndef _MSC_VER //linux #include #include #include #include #include #include #endif #include "StdAfx.h" #include "Serial.h" #include #include #include #include #include #define _POSIX_SOURCE 1 /* POSIX compliant source */ #define BAUDRATE B9600 #ifndef _MSC_VER // ugly hack, else will gcc not accept this constant in openLinux() const int flags = O_RDWR | O_NOCTTY ; //| O_NONBLOCK; #endif std::string writeLastError() { #ifdef _MSC_VER LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL); std::ostringstream out; out << "Error" << lpMsgBuf; return out.str(); #else //linux return std::string( strerror(errno) ); #endif } CSerial::CSerial() { mIsopen = false; } CSerial::CSerial(char* port, int bitrate) { mPortstr = port; mBitrate = bitrate; mIsopen = false; #ifdef _MSC_VER openWindows(); #else openLinux(); #endif } CSerial::~CSerial(void) { close(); } void CSerial::open(char* port, int bitrate) { if (mIsopen) throw std::runtime_error("Port already opened"); mPortstr = port; mBitrate = bitrate; #ifdef _MSC_VER openWindows(); #else openLinux(); #endif } #ifdef _MSC_VER void CSerial::openWindows() { mComport = CreateFile( mPortstr, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (mComport == INVALID_HANDLE_VALUE) { throw std::runtime_error(writeLastError().c_str()); } DCB dcb; dcb.DCBlength = sizeof(DCB); mDcbRestore.DCBlength = sizeof(DCB); if (!GetCommState(mComport,&dcb) || !GetCommState(mComport,&mDcbRestore)) { std::string error = writeLastError(); CloseHandle(mComport); throw std::exception(error.c_str()); } dcb.BaudRate = mBitrate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fParity = false; dcb.fDsrSensitivity = false; if (!SetCommState(mComport,&dcb)) { std::string error = writeLastError(); CloseHandle(mComport); throw std::runtime_error( error ); } mIsopen = true; } #endif #ifndef _MSC_VER void CSerial::openLinux() { termios newtio; std::cout << "opening port " << std::endl; mFiledescriptor = ::open(mPortstr, flags); if (mFiledescriptor < 0) throw std::runtime_error( writeLastError() ); std::cout << "port opened" << std::endl; bzero(&newtio, sizeof(newtio) ); // use a std. 8N1 config newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 0; /* blocking read until 1 chars received */ cfmakeraw(&newtio); cfsetospeed(&newtio, BAUDRATE); tcflush(mFiledescriptor, TCIFLUSH); tcsetattr(mFiledescriptor, TCSANOW, &newtio); std::cout << "port configured " << std::endl; mIsopen = true; } #endif void CSerial::close() { if (mIsopen) { #ifdef _MSC_VER while (getComstat().cbOutQue >0) Sleep(5); SetCommState(mComport,&mDcbRestore); CloseHandle(mComport); #else // linux close() tcdrain(mFiledescriptor); tcsetattr(mFiledescriptor, TCSADRAIN, &mOldtio); //restore settings, when all data is written ::close(mFiledescriptor); //close()== system-call #endif mIsopen = false; } } int CSerial::readByte() { unsigned char out; unsigned long size; if (!mIsopen) throw std::runtime_error("Port not opened"); #ifdef _MSC_VER ReadFile(mComport,&out,1,&size,0); if (size != 1) { std::string error = writeLastError(); CloseHandle(mComport); throw std::exception(error.c_str()); } #else //linux readByte() size = read(mFiledescriptor, &out, 1); if (size != 1) { std::cout << writeLastError() << std::endl; return -1; } #endif printByte("Read", out); return out; } void CSerial::writeByte(unsigned char out) { unsigned long size; printByte("Write", out); if (!mIsopen) throw std::runtime_error("Port not opened"); #ifdef _MSC_VER while (getComstat().cbOutQue >0) Sleep(2); WriteFile(mComport,&out,1,&size, NULL); if (size ==0) { std::string error = writeLastError(); CloseHandle(mComport); throw std::exception(error.c_str()); } #else //linux writeByte() //tcdrain(mFiledescriptor); size = write(mFiledescriptor,&out,1); Sleep(50); //tcdrain(mFiledescriptor); if (size != 1) throw std::runtime_error(writeLastError() ); #endif } #ifdef _MSC_VER COMSTAT CSerial::getComstat() const { if (!mIsopen) throw std::exception("Port not opened"); COMSTAT stat; DWORD x; ClearCommError(mComport,&x,&stat); return stat; } #endif int CSerial::bytesReady() const { #ifdef _MSC_VER return getComstat().cbInQue; #else return 0; #endif } int CSerial::outQueueSize() const { #ifdef _MSC_VER return getComstat().cbOutQue; #else return 0; #endif } // Debug function // void CSerial::printByte(char* description, unsigned char byte) { std::cout << description << " : " << (int) byte << "/" << std::setw(2) << std::setfill('0') << std::hex << (int) byte << std::endl; std::cout << std::dec; } /* void CSerial::writeBytes(UCVector out) { unsigned long bytesWritten; unsigned int size = out.size(); unsigned char *buf = new unsigned char[size]; for (int i=0; i