X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fio%2Fserial.cpp;h=09a9768023bad9e1fa00be0d398ac45a6933442c;hp=ec6a198bee3ac0d6d3568a9c218bac0df0f7aa4f;hb=ea8bf8f588310b0d7fd3297d74907602705bba1d;hpb=6e0fd758970bcb5bad5e3f2454b694cc4d7b4b66 diff --git a/source/io/serial.cpp b/source/io/serial.cpp index ec6a198..09a9768 100644 --- a/source/io/serial.cpp +++ b/source/io/serial.cpp @@ -1,188 +1,18 @@ -#ifdef WIN32 -#include -#else -#include -#include -#include -#endif -#include -#include "except.h" #include "serial.h" +#include "serial_private.h" using namespace std; -namespace { - -using namespace Msp; -using namespace Msp::IO; - -#ifdef WIN32 -typedef DCB DeviceState; -#else -typedef termios DeviceState; -#endif - -void get_state(Handle handle, DeviceState &state) -{ -#ifdef WIN32 - GetCommState(handle, &state); -#else - tcgetattr(handle, &state); -#endif -} - -void set_state(Handle handle, DeviceState &state) -{ -#ifdef WIN32 - if(SetCommState(handle, &state)==0) - throw SystemError("Cannot set serial port parameters", GetLastError()); -#else - if(tcsetattr(handle, TCSADRAIN, &state)==-1) - throw SystemError("Cannot set serial port parameters", errno); -#endif -} - -void set_baud_rate(DeviceState &state, unsigned baud) -{ -#ifdef WIN32 - state.BaudRate = baud; -#else - speed_t speed; - switch(baud) - { - case 0: speed = B0; break; - case 50: speed = B50; break; - case 75: speed = B75; break; - case 110: speed = B110; break; - case 134: speed = B134; break; - case 150: speed = B150; break; - case 200: speed = B200; break; - case 300: speed = B300; break; - case 600: speed = B600; break; - case 1200: speed = B1200; break; - case 1800: speed = B1800; break; - case 2400: speed = B2400; break; - case 4800: speed = B4800; break; - case 9600: speed = B9600; break; - case 19200: speed = B19200; break; - case 38400: speed = B38400; break; - case 57600: speed = B57600; break; - case 115200: speed = B115200; break; - case 230400: speed = B230400; break; - default: throw InvalidParameterValue("Invalid baud rate"); - } - - cfsetospeed(&state, speed); - cfsetispeed(&state, speed); -#endif -} - -void set_data_bits(DeviceState &state, unsigned bits) -{ -#ifdef WIN32 - state.ByteSize = bits; -#else - tcflag_t flag; - switch(bits) - { - case 5: flag = CS5; break; - case 6: flag = CS6; break; - case 7: flag = CS7; break; - case 8: flag = CS8; break; - default: throw InvalidParameterValue("Invalid data bit count"); - } - - state.c_cflag = (state.c_cflag&~CSIZE)|flag; -#endif -} - -void set_parity(DeviceState &state, Serial::Parity par) -{ -#ifdef WIN32 - switch(par) - { - case Serial::NONE: state.Parity = NOPARITY; break; - case Serial::EVEN: state.Parity = EVENPARITY; break; - case Serial::ODD: state.Parity = ODDPARITY; break; - default: throw InvalidParameterValue("Invalid parity"); - } -#else - tcflag_t flag; - switch(par) - { - case Serial::NONE: flag = 0; break; - case Serial::EVEN: flag = PARENB; break; - case Serial::ODD: flag = PARENB|PARODD; break; - default: throw InvalidParameterValue("Invalid parity"); - } - - state.c_cflag = (state.c_cflag&~(PARENB|PARODD))|flag; -#endif -} - -void set_stop_bits(DeviceState &state, unsigned bits) -{ -#ifdef WIN32 - switch(bits) - { - case 1: state.StopBits = ONESTOPBIT; break; - case 2: state.StopBits = TWOSTOPBITS; break; - default: throw InvalidParameterValue("Invalid stop bit count"); - } -#else - tcflag_t flag; - switch(bits) - { - case 1: flag = 0; break; - case 2: flag = CSTOPB; break; - default: throw InvalidParameterValue("Invalid stop bit count"); - } - - state.c_cflag = (state.c_cflag&~CSTOPB)|flag; -#endif -} - -} - - namespace Msp { namespace IO { -Serial::Serial(const string &descr) +Serial::Serial(const string &descr): + reader(handle, 1024) { string::size_type comma = descr.find(','); string port = descr.substr(0, comma); -#ifdef WIN32 - port = "\\\\.\\"+port; - - handle = CreateFile(port.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(handle==INVALID_HANDLE_VALUE) - throw SystemError(format("Can't open serial port '%s'", port), GetLastError()); - mode = M_READ|M_WRITE; - - COMMTIMEOUTS timeouts; - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; - timeouts.ReadTotalTimeoutConstant = MAXDWORD-1; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; - SetCommTimeouts(handle, &timeouts); -#else - if(port.compare(0, 5, "/dev/")) - port = "/dev/"+port; - - handle = open(port.c_str(), O_RDWR); - if(handle==-1) - throw SystemError(format("Can't open serial port '%s'", port), errno); - mode = M_READ|M_WRITE; - - termios t; - tcgetattr(handle, &t); - t.c_lflag &= ~(ECHO|ICANON); - t.c_oflag &= ~OPOST; - tcsetattr(handle, TCSADRAIN, &t); -#endif + platform_init(port); if(comma!=string::npos) { @@ -207,56 +37,51 @@ Serial::~Serial() void Serial::close() { -#ifdef WIN32 - CloseHandle(handle); -#else - ::close(handle); -#endif + sys_close(handle); } void Serial::set_block(bool b) { - if(b) - mode = mode|M_NONBLOCK; - else - mode = mode&~M_NONBLOCK; + adjust_mode(mode, M_NONBLOCK, !b); + sys_set_blocking(handle, b); +} -#ifndef WIN32 - int flags = fcntl(handle, F_GETFD); - fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); -#endif +void Serial::set_inherit(bool i) +{ + adjust_mode(mode, M_INHERIT, i); + sys_set_inherit(handle, i); } void Serial::set_baud_rate(unsigned rate) { DeviceState state; - get_state(handle, state); - ::set_baud_rate(state, rate); - set_state(handle, state); + state.get_from(handle); + state.set_baud_rate(rate); + state.apply_to(handle); } void Serial::set_data_bits(unsigned bits) { DeviceState state; - get_state(handle, state); - ::set_data_bits(state, bits); - set_state(handle, state); + state.get_from(handle); + state.set_data_bits(bits); + state.apply_to(handle); } void Serial::set_parity(Parity par) { DeviceState state; - get_state(handle, state); - ::set_parity(state, par); - set_state(handle, state); + state.get_from(handle); + state.set_parity(par); + state.apply_to(handle); } void Serial::set_stop_bits(unsigned bits) { DeviceState state; - get_state(handle, state); - ::set_stop_bits(state, bits); - set_state(handle, state); + state.get_from(handle); + state.set_stop_bits(bits); + state.apply_to(handle); } void Serial::set_parameters(const string ¶ms) @@ -264,21 +89,21 @@ void Serial::set_parameters(const string ¶ms) unsigned i; for(i=0; i'8') - throw InvalidParameterValue("Invalid data bit count"); + throw invalid_argument("Serial::set_parameters data_bits"); if(params[i+2]!='N' && params[i+2]!='E' && params[i+2]!='O') - throw InvalidParameterValue("Invalid parity"); + throw invalid_argument("Serial::set_parameters parity"); if(params[i+3]!='1' && params[i+3]!='2') - throw InvalidParameterValue("Invalid stop bit count"); + throw invalid_argument("Serial::set_parameters stop_bits"); DeviceState state; - get_state(handle, state); - ::set_baud_rate(state, lexical_cast(params.substr(0, i))); - ::set_data_bits(state, params[i+1]-'0'); - ::set_parity(state, (params[i+2]=='E' ? EVEN : params[i+2]=='O' ? ODD : NONE)); - ::set_stop_bits(state, params[i+3]-'0'); - set_state(handle, state); + state.get_from(handle); + state.set_baud_rate(lexical_cast(params.substr(0, i))); + state.set_data_bits(params[i+1]-'0'); + state.set_parity((params[i+2]=='E' ? EVEN : params[i+2]=='O' ? ODD : NONE)); + state.set_stop_bits(params[i+3]-'0'); + state.apply_to(handle); } unsigned Serial::do_write(const char *buf, unsigned size) @@ -286,22 +111,7 @@ unsigned Serial::do_write(const char *buf, unsigned size) if(size==0) return 0; -#ifdef WIN32 - DWORD ret; - if(WriteFile(handle, buf, size, &ret, 0)==0) - throw SystemError("Writing to serial port failed", GetLastError()); -#else - int ret = ::write(handle, buf, size); - if(ret==-1) - { - if(errno==EAGAIN) - return 0; - else - throw SystemError("Writing to serial port failed", errno); - } -#endif - - return ret; + return sys_write(handle, buf, size); } unsigned Serial::do_read(char *buf, unsigned size) @@ -309,31 +119,17 @@ unsigned Serial::do_read(char *buf, unsigned size) if(size==0) return 0; -#ifdef WIN32 - DWORD ret; - if(ReadFile(handle, buf, size, &ret, 0)==0) - throw SystemError("Reading from serial port failed", GetLastError()); -#else - int ret = ::read(handle, buf, size); - if(ret==-1) - { - if(errno==EAGAIN) - return 0; - else - throw SystemError("Reading from serial port failed", errno); - } -#endif + unsigned ret = reader.read(buf, size); + if(ret==0) + set_eof(); return ret; } -Handle Serial::get_event_handle() +const Handle &Serial::get_handle(Mode m) { -#ifdef WIN32 - throw Exception("Serial port events not supported on win32 yet"); -#else + check_access(m); return handle; -#endif } } // namespace IO