3 This file is part of libmspio
4 Copyright © 2010 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
11 #include <msp/strings/formatter.h>
20 using namespace Msp::IO;
23 void set_baud_rate(termios &t, unsigned baud)
28 case 0: speed = B0; break;
29 case 50: speed = B50; break;
30 case 75: speed = B75; break;
31 case 110: speed = B110; break;
32 case 134: speed = B134; break;
33 case 150: speed = B150; break;
34 case 200: speed = B200; break;
35 case 300: speed = B300; break;
36 case 600: speed = B600; break;
37 case 1200: speed = B1200; break;
38 case 1800: speed = B1800; break;
39 case 2400: speed = B2400; break;
40 case 4800: speed = B4800; break;
41 case 9600: speed = B9600; break;
42 case 19200: speed = B19200; break;
43 case 38400: speed = B38400; break;
44 case 57600: speed = B57600; break;
45 case 115200: speed = B115200; break;
46 case 230400: speed = B230400; break;
47 default: throw InvalidParameterValue("Invalid baud rate");
50 cfsetospeed(&t, speed);
51 cfsetispeed(&t, speed);
54 void set_data_bits(termios &t, unsigned bits)
59 case 5: flag = CS5; break;
60 case 6: flag = CS6; break;
61 case 7: flag = CS7; break;
62 case 8: flag = CS8; break;
63 default: throw InvalidParameterValue("Invalid data bit count");
66 t.c_cflag = (t.c_cflag&~CSIZE)|flag;
69 void set_parity(termios &t, Serial::Parity par)
74 case Serial::NONE: flag = 0; break;
75 case Serial::EVEN: flag = PARENB; break;
76 case Serial::ODD: flag = PARENB|PARODD; break;
77 default: throw InvalidParameterValue("Invalid parity");
80 t.c_cflag = (t.c_cflag&~(PARENB|PARODD))|flag;
83 void set_stop_bits(termios &t, unsigned bits)
88 case 1: flag = 0; break;
89 case 2: flag = CSTOPB; break;
90 default: throw InvalidParameterValue("Invalid stop bit count");
93 t.c_cflag = (t.c_cflag&~CSTOPB)|flag;
103 Serial::Serial(const string &descr)
105 string::size_type comma = descr.find(',');
106 string port = descr.substr(0, comma);
109 if(port.compare(0, 5, "/dev/"))
112 handle = open(port.c_str(), O_RDWR);
114 throw SystemError(format("Can't open serial port '%s'", port), errno);
115 mode = M_READ|M_WRITE;
118 tcgetattr(handle, &t);
119 t.c_lflag &= ~(ECHO|ICANON);
120 tcsetattr(handle, TCSADRAIN, &t);
122 throw Exception("Serial ports not supported in win32 yet");
125 if(comma!=string::npos)
129 set_parameters(descr.substr(comma+1));
146 void Serial::set_block(bool b)
149 mode = mode|M_NONBLOCK;
151 mode = mode&~M_NONBLOCK;
154 int flags = fcntl(handle, F_GETFD);
155 fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
159 void Serial::set_baud_rate(unsigned rate)
163 tcgetattr(handle, &t);
164 ::set_baud_rate(t, rate);
165 tcsetattr(handle, TCSADRAIN, &t);
169 void Serial::set_data_bits(unsigned bits)
173 tcgetattr(handle, &t);
174 ::set_data_bits(t, bits);
175 tcsetattr(handle, TCSADRAIN, &t);
179 void Serial::set_parity(Parity par)
183 tcgetattr(handle, &t);
184 ::set_parity(t, par);
185 tcsetattr(handle, TCSADRAIN, &t);
189 void Serial::set_stop_bits(unsigned bits)
193 tcgetattr(handle, &t);
194 ::set_stop_bits(t, bits);
195 tcsetattr(handle, TCSADRAIN, &t);
199 void Serial::set_parameters(const string ¶ms)
202 for(i=0; i<params.size() && isdigit(params[i]); ++i) ;
203 if(i+4!=params.size() || params[i]!=',')
204 throw InvalidParameterValue("Invalid parameter string");
205 if(params[i+1]<'5' || params[i+1]>'8')
206 throw InvalidParameterValue("Invalid data bit count");
207 if(params[i+2]!='N' && params[i+2]!='E' && params[i+2]!='O')
208 throw InvalidParameterValue("Invalid parity");
209 if(params[i+3]!='1' && params[i+3]!='2')
210 throw InvalidParameterValue("Invalid stop bit count");
214 tcgetattr(handle, &t);
215 ::set_baud_rate(t, lexical_cast<unsigned>(params.substr(0, i)));
216 ::set_data_bits(t, params[i+1]-'0');
217 ::set_parity(t, (params[i+2]=='E' ? EVEN : params[i+2]=='O' ? ODD : NONE));
218 ::set_stop_bits(t, params[i+3]-'0');
219 tcsetattr(handle, TCSADRAIN, &t);
230 unsigned Serial::do_write(const char *buf, unsigned size)
236 int ret = ::write(handle, buf, size);
242 throw SystemError("Writing to serial port failed", errno);
249 unsigned Serial::do_read(char *buf, unsigned size)
255 int ret = ::read(handle, buf, size);
261 throw SystemError("Reading from serial port failed", errno);