--- branches/linux-serial/Serial.cpp 2007/02/04 21:22:44 44 +++ branches/linux-serial/Serial.cpp 2007/02/05 10:11:47 55 @@ -1,19 +1,32 @@ -#ifdef _WINDOWS -#include "StdAfx.h" -#else //linux +#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 _WINDOWS +#ifdef _MSC_VER LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, @@ -27,9 +40,7 @@ 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 +50,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 +69,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 +77,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 +105,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 +118,7 @@ { std::string error = writeLastError(); CloseHandle(mComport); - throw std::exception(error.c_str()); + throw std::runtime_error( error ); } mIsopen = true; @@ -114,9 +126,41 @@ #endif -#ifndef _WINDOWS +#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 = convertBaudrate(mBitrate) | 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, B9600 ); + cfsetispeed(&newtio, B9600 ); +*/ + + tcflush(mFiledescriptor, TCIFLUSH); + tcsetattr(mFiledescriptor, TCSANOW, &newtio); + + std::cout << "port configured " << std::endl; + mIsopen = true; } #endif @@ -124,26 +168,29 @@ { 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; if (!mIsopen) throw std::runtime_error("Port not opened"); -#ifdef _WINDOWS +#ifdef _MSC_VER ReadFile(mComport,&out,1,&size,0); if (size != 1) { @@ -152,9 +199,15 @@ 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); + printByte("Read", out); return out; } @@ -163,11 +216,11 @@ { unsigned long size; - //printByte("Write", out); + printByte("Write", out); if (!mIsopen) throw std::runtime_error("Port not opened"); -#ifdef _WINDOWS +#ifdef _MSC_VER while (getComstat().cbOutQue >0) Sleep(2); @@ -179,9 +232,92 @@ 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 _WINDOWS + +int CSerial::convertBaudrate(Baudrate rate) +{ + int retval=0; +#ifdef _MSC_VER + switch( rate ) + { + 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; + } +#endif + + return retval; +} + +#ifdef _MSC_VER COMSTAT CSerial::getComstat() const { if (!mIsopen) @@ -196,7 +332,7 @@ int CSerial::bytesReady() const { -#ifdef _WINDOWS +#ifdef _MSC_VER return getComstat().cbInQue; #else return 0; @@ -205,20 +341,21 @@ 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) { 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)