3 * Copyright (C) Bob 2009
5 * boblight is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * boblight is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "../serialport.h"
22 #include "../baudrate.h"
23 #include "../timeutils.h"
28 CSerialPort::CSerialPort()
33 CSerialPort::~CSerialPort()
38 int CSerialPort::Write(uint8_t* data
, int len
)
42 CLockObject
lock(&m_mutex
);
45 m_error
= "port closed";
51 while (byteswritten
< len
)
55 int returnv
= select(m_fd
+ 1, NULL
, &port
, NULL
, NULL
);
58 m_error
= strerror(errno
);
62 returnv
= write(m_fd
, data
+ byteswritten
, len
- byteswritten
);
65 m_error
= strerror(errno
);
68 byteswritten
+= returnv
;
71 //print what's written to stdout for debugging
74 // printf("%s write:", m_name.c_str());
75 // for (int i = 0; i < byteswritten; i++)
76 // printf(" %02x", (unsigned int)data[i]);
84 int CSerialPort::Read(uint8_t* data
, int len
, int iTimeoutMs
/*= -1*/)
87 struct timeval timeout
, *tv
;
91 CLockObject
lock(&m_mutex
);
94 m_error
= "port closed";
101 target
= now
+ (int64_t) iTimeoutMs
;
104 while (bytesread
< len
&& (iTimeoutMs
< 0 || target
> now
))
112 timeout
.tv_sec
= ((long int)target
- (long int)now
) / (long int)1000.;
113 timeout
.tv_usec
= ((long int)target
- (long int)now
) % (long int)1000.;
119 int returnv
= select(m_fd
+ 1, &port
, NULL
, NULL
, tv
);
123 m_error
= strerror(errno
);
126 else if (returnv
== 0)
128 break; //nothing to read
131 returnv
= read(m_fd
, data
+ bytesread
, len
- bytesread
);
134 m_error
= strerror(errno
);
138 bytesread
+= returnv
;
144 //print what's read to stdout for debugging
145 // if (m_tostdout && bytesread > 0)
147 // printf("%s read:", m_name.c_str());
148 // for (int i = 0; i < bytesread; i++)
149 // printf(" %02x", (unsigned int)data[i]);
157 //setting all this stuff up is a pain in the ass
158 bool CSerialPort::Open(string name
, int baudrate
, int databits
/* = 8*/, int stopbits
/* = 1*/, int parity
/* = PAR_NONE*/)
161 m_error
= strerror(errno
);
162 CLockObject
lock(&m_mutex
);
164 if (databits
< 5 || databits
> 8)
166 m_error
= "Databits has to be between 5 and 8";
170 if (stopbits
!= 1 && stopbits
!= 2)
172 m_error
= "Stopbits has to be 1 or 2";
176 if (parity
!= PAR_NONE
&& parity
!= PAR_EVEN
&& parity
!= PAR_ODD
)
178 m_error
= "Parity has to be none, even or odd";
182 m_fd
= open(name
.c_str(), O_RDWR
| O_NOCTTY
| O_NDELAY
);
186 m_error
= strerror(errno
);
190 fcntl(m_fd
, F_SETFL
, 0);
192 if (!SetBaudRate(baudrate
))
197 m_options
.c_cflag
|= (CLOCAL
| CREAD
);
198 m_options
.c_cflag
&= ~HUPCL
;
200 m_options
.c_cflag
&= ~CSIZE
;
201 if (databits
== 5) m_options
.c_cflag
|= CS5
;
202 if (databits
== 6) m_options
.c_cflag
|= CS6
;
203 if (databits
== 7) m_options
.c_cflag
|= CS7
;
204 if (databits
== 8) m_options
.c_cflag
|= CS8
;
206 m_options
.c_cflag
&= ~PARENB
;
207 if (parity
== PAR_EVEN
|| parity
== PAR_ODD
)
208 m_options
.c_cflag
|= PARENB
;
209 if (parity
== PAR_ODD
)
210 m_options
.c_cflag
|= PARODD
;
213 m_options
.c_cflag
&= ~CRTSCTS
;
214 #elif defined(CNEW_RTSCTS)
215 m_options
.c_cflag
&= ~CNEW_RTSCTS
;
218 if (stopbits
== 1) m_options
.c_cflag
&= ~CSTOPB
;
219 else m_options
.c_cflag
|= CSTOPB
;
221 //I guessed a little here
222 m_options
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
| XCASE
| ECHOK
| ECHONL
| ECHOCTL
| ECHOPRT
| ECHOKE
| TOSTOP
);
224 if (parity
== PAR_NONE
)
226 m_options
.c_iflag
&= ~INPCK
;
230 m_options
.c_iflag
|= INPCK
| ISTRIP
;
233 m_options
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
| BRKINT
| INLCR
| IGNCR
| ICRNL
| IUCLC
| IMAXBEL
);
234 m_options
.c_oflag
&= ~(OPOST
| ONLCR
| OCRNL
);
236 if (tcsetattr(m_fd
, TCSANOW
, &m_options
) != 0)
238 m_error
= strerror(errno
);
243 fcntl(m_fd
, F_SETFL
, FNDELAY
);
248 void CSerialPort::Close()
250 CLockObject
lock(&m_mutex
);
260 bool CSerialPort::SetBaudRate(int baudrate
)
262 int rate
= IntToBaudrate(baudrate
);
266 sprintf(buff
, "%i is not a valid baudrate", baudrate
);
271 //get the current port attributes
272 if (tcgetattr(m_fd
, &m_options
) != 0)
274 m_error
= strerror(errno
);
278 if (cfsetispeed(&m_options
, rate
) != 0)
280 m_error
= strerror(errno
);
284 if (cfsetospeed(&m_options
, rate
) != 0)
286 m_error
= strerror(errno
);
293 bool CSerialPort::IsOpen()
295 CLockObject
lock(&m_mutex
);