--- branches/linux-serial/Serial.cpp 2007/02/04 21:22:44 44 +++ branches/linux-serial/Serial.cpp 2008/06/04 13:06:09 76 @@ -1,7 +1,10 @@ -#ifdef _WINDOWS -#include "StdAfx.h" -#else //linux +#ifndef _MSC_VER //linux +#include +#include +#include #include +#include +#include #endif #include "Serial.h" @@ -9,11 +12,19 @@ #include #include #include + + +#ifdef DEBUG +#include #include +#endif + + + std::string writeLastError() { -#ifdef _WINDOWS +#ifdef _MSC_VER LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, @@ -24,12 +35,10 @@ NULL); std::ostringstream out; - out << "Error" << lpMsgBuf; + out << "Error " << lpMsgBuf; return out.str(); #else //linux - char message[256]; - strerror_r(errno, message, 255); - return std::string(message); + return std::string( strerror(errno) ); #endif } @@ -39,13 +48,14 @@ mIsopen = false; } -CSerial::CSerial(char* port, int bitrate) + +CSerial::CSerial(char* port, Baudrate bitrate) { mPortstr = port; mBitrate = bitrate; mIsopen = false; -#ifdef _WINDOWS +#ifdef _MSC_VER openWindows(); #else openLinux(); @@ -57,7 +67,7 @@ close(); } -void CSerial::open(char* port, int bitrate) +void CSerial::open(char* port, Baudrate bitrate) { if (mIsopen) throw std::runtime_error("Port already opened"); @@ -65,14 +75,14 @@ mPortstr = port; mBitrate = bitrate; -#ifdef _WINDOWS +#ifdef _MSC_VER openWindows(); #else openLinux(); #endif } -#ifdef _WINDOWS +#ifdef _MSC_VER void CSerial::openWindows() { mComport = CreateFile( mPortstr, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); @@ -93,7 +103,7 @@ throw std::exception(error.c_str()); } - dcb.BaudRate = mBitrate; + dcb.BaudRate = convertBaudrate(mBitrate); dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; @@ -106,7 +116,7 @@ { std::string error = writeLastError(); CloseHandle(mComport); - throw std::exception(error.c_str()); + throw std::runtime_error( error ); } mIsopen = true; @@ -114,9 +124,35 @@ #endif -#ifndef _WINDOWS +#ifndef _MSC_VER void CSerial::openLinux() { + termios newtio; + + mFiledescriptor = ::open(mPortstr, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (mFiledescriptor < 0) + throw std::runtime_error( writeLastError() ); + + tcgetattr(mFiledescriptor, &mOldtio); + + bzero(&newtio, sizeof(newtio) ); + + // use a std. 8N1 config + newtio.c_cflag = convertBaudrate(mBitrate) | 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 + + + tcflush(mFiledescriptor, TCIFLUSH); + tcsetattr(mFiledescriptor, TCSANOW, &newtio); + + mIsopen = true; } #endif @@ -124,64 +160,115 @@ { if (mIsopen) { -#ifdef _WINDOWS +#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; } } -unsigned char CSerial::readByte() +int CSerial::readByte() { unsigned char out; - unsigned long size; + int size = readBytes(&out,1); - if (!mIsopen) - throw std::runtime_error("Port not opened"); -#ifdef _WINDOWS - ReadFile(mComport,&out,1,&size,0); - if (size != 1) - { - std::string error = writeLastError(); - CloseHandle(mComport); - throw std::exception(error.c_str()); - } -#else //linux readByte() -#endif + if (size == 0) + return 256; - //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 _WINDOWS - while (getComstat().cbOutQue >0) - Sleep(2); + writeBytes(&out,1); +} - WriteFile(mComport,&out,1,&size, NULL); - if (size ==0) +int CSerial::convertBaudrate(Baudrate rate) +{ + int retval=0; +#ifdef _MSC_VER + switch( rate ) { - std::string error = writeLastError(); - CloseHandle(mComport); - throw std::exception(error.c_str()); + case Baud300: + retval = 300; + break; + case Baud600: + retval = 600; + break; + case Baud1200: + retval = 1200; + break; + case Baud2400: + retval = 2400; + break; + case Baud4800: + retval = 4800; + break; + case Baud9600: + retval = 9600; + break; + case Baud19200: + retval = 19200; + break; + case Baud38400: + retval = 38400; + break; + case Baud57600: + retval = 57600; + break; + case Baud115200: + retval = 115200; + break; + } +#else + switch (rate) + { + case Baud300: + retval = B300; + break; + case Baud600: + retval = B600; + break; + case Baud1200: + retval = B1200; + break; + case Baud2400: + retval = B2400; + break; + case Baud4800: + retval = B4800; + break; + case Baud9600: + retval = B9600; + break; + case Baud19200: + retval = B19200; + break; + case Baud38400: + retval = B38400; + break; + case Baud57600: + retval = B57600; + break; + case Baud115200: + retval = B115200; + break; } -#else //linux writeByte() #endif + + return retval; } -#ifdef _WINDOWS + +#ifdef _MSC_VER COMSTAT CSerial::getComstat() const { if (!mIsopen) @@ -196,7 +283,7 @@ int CSerial::bytesReady() const { -#ifdef _WINDOWS +#ifdef _MSC_VER return getComstat().cbInQue; #else return 0; @@ -205,50 +292,89 @@ int CSerial::outQueueSize() const { -#ifdef _WINDOWS +#ifdef _MSC_VER return getComstat().cbOutQue; #else return 0; #endif } -/* Debug function +// Debug function +// void CSerial::printByte(char* description, unsigned char byte) { +#ifdef DEBUG std::cout << description << " : " << (int) byte << "/" << std::setw(2) << std::setfill('0') << std::hex << (int) byte << std::endl; std::cout << std::dec; +#endif } -*/ -/* -void CSerial::writeBytes(UCVector out) + + +void CSerial::writeBytes(unsigned char* buf, unsigned int len) { - unsigned long bytesWritten; - unsigned int size = out.size(); - unsigned char *buf = new unsigned char[size]; + if (!mIsopen) + throw std::runtime_error("Port not opened"); +#ifdef _MSC_VER + writeBytesWindows(buf,len); +#else + writeBytesLinux(buf,len); +#endif +} - for (int i=0; i0) + Sleep(2); + + WriteFile(mComport,buf,len,&size, NULL); + if (size != len) { std::string error = writeLastError(); CloseHandle(mComport); throw std::exception(error.c_str()); } - delete[] buf; } -*/ +#else +void CSerial::writeBytesLinux(unsigned char* buf, unsigned int len) +{ + int size = write(mFiledescriptor, &buf, len); + Sleep(50); + //tcdrain(mFiledescriptor); + if (size != len) + throw std::runtime_error(writeLastError() ); +} +#endif -/* -UCVector CSerial::readBytes(int maxcount) +int CSerial::readBytes(unsigned char *buf, unsigned int maxLen) { - UCVector buf; + if (!mIsopen) + throw std::runtime_error("Port not opened"); +#ifdef _MSC_VER + return readBytesWindows(buf,maxLen); +#else + return readBytesLinux(buf,maxLen); +#endif +} +#ifdef _MSC_VER +int CSerial::readBytesWindows(unsigned char* buf, unsigned int maxLen) +{ + unsigned long size; + ReadFile(mComport, buf, maxLen, &size, 0); + return size; +} + +#else - return buf; +int CSerial::readBytesLinux(unsigned char* buf, unsigned int maxLen) +{ + return read(mFiledescriptor, buf, maxLen); } -*/ + +#endif