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"
25 #if defined(__APPLE__)
39 CSerialPort::CSerialPort()
44 CSerialPort::~CSerialPort()
49 int8_t CSerialPort::Write(const cec_adapter_message
&data
)
53 CLockObject
lock(&m_mutex
);
56 m_error
= "port closed";
60 int32_t byteswritten
= 0;
62 while (byteswritten
< (int32_t) data
.size())
66 int returnv
= select(m_fd
+ 1, NULL
, &port
, NULL
, NULL
);
69 m_error
= strerror(errno
);
73 returnv
= write(m_fd
, data
.packet
.data
+ byteswritten
, data
.size() - byteswritten
);
76 m_error
= strerror(errno
);
79 byteswritten
+= returnv
;
82 //print what's written to stdout for debugging
85 // printf("%s write:", m_name.c_str());
86 // for (int i = 0; i < byteswritten; i++)
87 // printf(" %02x", (unsigned int)data[i]);
95 int32_t CSerialPort::Read(uint8_t* data
, uint32_t len
, uint64_t iTimeoutMs
/*= 0*/)
98 struct timeval timeout
, *tv
;
99 int64_t now(0), target(0);
100 int32_t bytesread
= 0;
102 CLockObject
lock(&m_mutex
);
105 m_error
= "port closed";
112 target
= now
+ (int64_t) iTimeoutMs
;
115 while (bytesread
< (int32_t) len
&& (iTimeoutMs
== 0 || target
> now
))
123 timeout
.tv_sec
= ((long int)target
- (long int)now
) / (long int)1000.;
124 timeout
.tv_usec
= ((long int)target
- (long int)now
) % (long int)1000.;
130 int32_t returnv
= select(m_fd
+ 1, &port
, NULL
, NULL
, tv
);
134 m_error
= strerror(errno
);
137 else if (returnv
== 0)
139 break; //nothing to read
142 returnv
= read(m_fd
, data
+ bytesread
, len
- bytesread
);
145 m_error
= strerror(errno
);
149 bytesread
+= returnv
;
155 //print what's read to stdout for debugging
156 // if (m_tostdout && bytesread > 0)
158 // printf("%s read:", m_name.c_str());
159 // for (int i = 0; i < bytesread; i++)
160 // printf(" %02x", (unsigned int)data[i]);
168 //setting all this stuff up is a pain in the ass
169 bool CSerialPort::Open(string name
, uint32_t baudrate
, uint8_t databits
/* = 8 */, uint8_t stopbits
/* = 1 */, uint8_t parity
/* = PAR_NONE */)
172 m_error
= strerror(errno
);
173 CLockObject
lock(&m_mutex
);
175 if (databits
< 5 || databits
> 8)
177 m_error
= "Databits has to be between 5 and 8";
181 if (stopbits
!= 1 && stopbits
!= 2)
183 m_error
= "Stopbits has to be 1 or 2";
187 if (parity
!= PAR_NONE
&& parity
!= PAR_EVEN
&& parity
!= PAR_ODD
)
189 m_error
= "Parity has to be none, even or odd";
193 m_fd
= open(name
.c_str(), O_RDWR
| O_NOCTTY
| O_NDELAY
);
197 m_error
= strerror(errno
);
201 fcntl(m_fd
, F_SETFL
, 0);
203 if (!SetBaudRate(baudrate
))
208 m_options
.c_cflag
|= (CLOCAL
| CREAD
);
209 m_options
.c_cflag
&= ~HUPCL
;
211 m_options
.c_cflag
&= ~CSIZE
;
212 if (databits
== 5) m_options
.c_cflag
|= CS5
;
213 if (databits
== 6) m_options
.c_cflag
|= CS6
;
214 if (databits
== 7) m_options
.c_cflag
|= CS7
;
215 if (databits
== 8) m_options
.c_cflag
|= CS8
;
217 m_options
.c_cflag
&= ~PARENB
;
218 if (parity
== PAR_EVEN
|| parity
== PAR_ODD
)
219 m_options
.c_cflag
|= PARENB
;
220 if (parity
== PAR_ODD
)
221 m_options
.c_cflag
|= PARODD
;
224 m_options
.c_cflag
&= ~CRTSCTS
;
225 #elif defined(CNEW_RTSCTS)
226 m_options
.c_cflag
&= ~CNEW_RTSCTS
;
229 if (stopbits
== 1) m_options
.c_cflag
&= ~CSTOPB
;
230 else m_options
.c_cflag
|= CSTOPB
;
232 //I guessed a little here
233 m_options
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
| XCASE
| ECHOK
| ECHONL
| ECHOCTL
| ECHOPRT
| ECHOKE
| TOSTOP
);
235 if (parity
== PAR_NONE
)
237 m_options
.c_iflag
&= ~INPCK
;
241 m_options
.c_iflag
|= INPCK
| ISTRIP
;
244 m_options
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
| BRKINT
| INLCR
| IGNCR
| ICRNL
| IUCLC
| IMAXBEL
);
245 m_options
.c_oflag
&= ~(OPOST
| ONLCR
| OCRNL
);
247 if (tcsetattr(m_fd
, TCSANOW
, &m_options
) != 0)
249 m_error
= strerror(errno
);
254 fcntl(m_fd
, F_SETFL
, FNDELAY
);
259 void CSerialPort::Close()
261 CLockObject
lock(&m_mutex
);
271 bool CSerialPort::SetBaudRate(uint32_t baudrate
)
273 int rate
= IntToBaudrate(baudrate
);
277 sprintf(buff
, "%i is not a valid baudrate", baudrate
);
282 //get the current port attributes
283 if (tcgetattr(m_fd
, &m_options
) != 0)
285 m_error
= strerror(errno
);
289 if (cfsetispeed(&m_options
, rate
) != 0)
291 m_error
= strerror(errno
);
295 if (cfsetospeed(&m_options
, rate
) != 0)
297 m_error
= strerror(errno
);
304 bool CSerialPort::IsOpen()
306 CLockObject
lock(&m_mutex
);