impl_win.cpp
Go to the documentation of this file.
1 /***
2  * MIT License
3  *
4  * Copyright (c) 2020 Alessandro Tondo
5  * Copyright (c) 2012 William Woodall, John Harrison
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8  * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
10  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
13  * the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
16  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19  * SOFTWARE.
20  */
21 
22 #if defined(_WIN32)
23 
24 #include <serial/impl/impl.h>
25 
26 using namespace serial;
27 
28 Serial::SerialImpl::SerialImpl(std::string port, unsigned long baudrate, Timeout timeout, bytesize_t bytesize,
29  parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol)
30  : port_(std::move(port)),
32  is_open_(false),
33  timeout_(timeout),
34  baudrate_(baudrate),
35  parity_(parity),
36  bytesize_(bytesize),
37  stopbits_(stopbits),
38  flowcontrol_(flowcontrol) {
39  if (!port_.empty()) {
40  open();
41  }
42 }
43 
45  close();
46 }
47 
49  if (port_.empty()) {
50  throw SerialInvalidArgumentException("serial port is empty.");
51  }
52  if (is_open_) {
53  return;
54  }
55 
56  std::string escaped_port = escape(port_);
57  fd_ = ::CreateFileW(std::wstring(escaped_port.begin(), escaped_port.end()).c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
58  if (fd_ == INVALID_HANDLE_VALUE) {
59  throw SerialIOException("failure during ::CreateFileW()", ::GetLastError());
60  }
61 
62  reconfigurePort();
63  is_open_ = true;
64 }
65 
67  if (fd_ == INVALID_HANDLE_VALUE) {
68  throw SerialInvalidArgumentException("invalid file descriptor");
69  }
70 
71  DCB dcbSerialParams = {0};
72  dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
73  if (!::GetCommState(fd_, &dcbSerialParams)) {
74  throw SerialIOException("failure during ::GetCommState()", ::GetLastError());
75  }
76 
77  dcbSerialParams.BaudRate = baudrate_;
78 
79  switch (bytesize_) {
80  case eightbits: dcbSerialParams.ByteSize = 8; break;
81  case sevenbits: dcbSerialParams.ByteSize = 7; break;
82  case sixbits: dcbSerialParams.ByteSize = 6; break;
83  case fivebits: dcbSerialParams.ByteSize = 5; break;
84  default:
85  throw SerialInvalidArgumentException("invalid byte size");
86  }
87 
88  switch (stopbits_) {
89  case stopbits_one: dcbSerialParams.StopBits = ONESTOPBIT; break;
90  case stopbits_one_point_five: dcbSerialParams.StopBits = ONE5STOPBITS; break;
91  case stopbits_two: dcbSerialParams.StopBits = TWOSTOPBITS; break;
92  default:
93  throw SerialInvalidArgumentException("invalid stop bit");
94  }
95 
96  switch (parity_) {
97  case parity_none: dcbSerialParams.Parity = NOPARITY; break;
98  case parity_even: dcbSerialParams.Parity = EVENPARITY; break;
99  case parity_odd: dcbSerialParams.Parity = ODDPARITY; break;
100  case parity_mark: dcbSerialParams.Parity = MARKPARITY; break;
101  case parity_space: dcbSerialParams.Parity = SPACEPARITY; break;
102  default:
103  throw SerialInvalidArgumentException("invalid parity");
104  }
105 
106  //TODO: missing fOutxDsrFlow and fDtrControl (and many others)
107  switch (flowcontrol_) {
108  case flowcontrol_none:
109  dcbSerialParams.fOutxCtsFlow = false;
110  dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
111  dcbSerialParams.fOutX = false;
112  dcbSerialParams.fInX = false;
113  break;
115  dcbSerialParams.fOutxCtsFlow = false;
116  dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
117  dcbSerialParams.fOutX = true;
118  dcbSerialParams.fInX = true;
119  break;
121  dcbSerialParams.fOutxCtsFlow = true;
122  dcbSerialParams.fRtsControl = RTS_CONTROL_HANDSHAKE;
123  dcbSerialParams.fOutX = false;
124  dcbSerialParams.fInX = false;
125  break;
126  default:
127  throw SerialInvalidArgumentException("invalid flow control");
128  }
129 
130  if (!::SetCommState(fd_, &dcbSerialParams)) {
131  throw SerialIOException("failure during ::SetCommState()", ::GetLastError());
132  }
133 
134  COMMTIMEOUTS timeouts = {0};
135  timeouts.ReadIntervalTimeout = timeout_.getInterByteMilliseconds();
136  timeouts.ReadTotalTimeoutConstant = timeout_.getReadConstantMilliseconds();
137  timeouts.ReadTotalTimeoutMultiplier = timeout_.getReadMultiplierMilliseconds();
138  timeouts.WriteTotalTimeoutConstant = timeout_.getWriteConstantMilliseconds();
139  timeouts.WriteTotalTimeoutMultiplier = timeout_.getWriteMultiplierMilliseconds();
140  if (!::SetCommTimeouts(fd_, &timeouts)) {
141  throw SerialIOException("failure during ::SetCommTimeouts()", ::GetLastError());
142  }
143 }
144 
146  if (is_open_ && fd_ != INVALID_HANDLE_VALUE && !::CloseHandle(fd_)) {
147  throw SerialIOException("failure during ::CloseHandle()", ::GetLastError());
148  }
149  fd_ = INVALID_HANDLE_VALUE;
150  is_open_ = false;
151 }
152 
153 bool Serial::SerialImpl::isOpen() const {
154  return is_open_;
155 }
156 
157 size_t Serial::SerialImpl::available() const {
158  if (!is_open_) {
160  }
161  COMSTAT stat;
162  if (!::ClearCommError(fd_, nullptr, &stat)) {
163  throw SerialIOException("during ::ClearCommError()", ::GetLastError());
164  }
165  return static_cast<size_t>(stat.cbInQue);
166 }
167 
168 bool Serial::SerialImpl::waitReadable(std::chrono::milliseconds timeout_ms) const {
169  throw SerialException("waitReadable() is not implemented on Windows");
170  //TODO: have a deeper look at WaitForSingleObject
171 }
172 
173 bool Serial::SerialImpl::waitWritable(std::chrono::milliseconds timeout_ms) const {
174  throw SerialException("waitWritable() is not implemented on Windows");
175  //TODO: have a deeper look at WaitForSingleObject
176 }
177 
178 void Serial::SerialImpl::waitByteTimes(size_t count) const {
179  auto start = std::chrono::steady_clock::now();
180  uint32_t bit_time_ns = 1e9 / baudrate_;
181  uint32_t byte_time_ns = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_);
182  byte_time_ns += stopbits_ == stopbits_one_point_five ? -1.5*bit_time_ns : 0; // stopbits_one_point_five is 3
183  std::this_thread::sleep_until(start + std::chrono::nanoseconds(byte_time_ns * count));
184 }
185 
186 size_t Serial::SerialImpl::read(uint8_t *buf, size_t size) {
187  if (!is_open_) {
189  }
190  DWORD bytes_read = 0;
191  if (!::ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, nullptr)) {
192  throw SerialIOException("during ::ReadFile()", ::GetLastError());
193  }
194  return static_cast<size_t>(bytes_read);
195 }
196 
197 size_t Serial::SerialImpl::write(const uint8_t *data, size_t size) {
198  if (!is_open_) {
200  }
201  DWORD bytes_written = 0;
202  if (!::WriteFile(fd_, data, static_cast<DWORD>(size), &bytes_written, nullptr)) {
203  throw SerialIOException("during ::WriteFile()", ::GetLastError());
204  }
205  return static_cast<size_t>(bytes_written);
206 }
207 
208 void Serial::SerialImpl::setPort(const std::string &port) {
209  port_ = port;
210 }
211 
212 std::string Serial::SerialImpl::getPort() const {
213  return port_;
214 }
215 
216 void Serial::SerialImpl::setTimeout(const Timeout &timeout) {
217  timeout_ = timeout;
218  if (is_open_) {
219  reconfigurePort();
220  }
221 }
222 
224  return timeout_;
225 }
226 
227 void Serial::SerialImpl::setBaudrate(unsigned long baudrate) {
228  baudrate_ = baudrate;
229  if (is_open_) {
230  reconfigurePort();
231  }
232 }
233 
234 unsigned long Serial::SerialImpl::getBaudrate() const {
235  return baudrate_;
236 }
237 
239  bytesize_ = bytesize;
240  if (is_open_) {
241  reconfigurePort();
242  }
243 }
244 
246  return bytesize_;
247 }
248 
250  parity_ = parity;
251  if (is_open_) {
252  reconfigurePort();
253  }
254 }
255 
257  return parity_;
258 }
259 
261  stopbits_ = stopbits;
262  if (is_open_) {
263  reconfigurePort();
264  }
265 }
266 
268  return stopbits_;
269 }
270 
272  flowcontrol_ = flowcontrol;
273  if (is_open_) {
274  reconfigurePort();
275  }
276 }
277 
279  return flowcontrol_;
280 }
281 
282 void Serial::SerialImpl::flush() const {
283  if (!is_open_) {
285  }
286  if (!::PurgeComm(fd_, PURGE_RXCLEAR | PURGE_TXCLEAR)) {
287  throw SerialIOException("failure during ::EscapeCommFunction()");
288  }
289 }
290 
291 void Serial::SerialImpl::flushInput() const {
292  if (!is_open_) {
294  }
295  if (!::PurgeComm(fd_, PURGE_RXCLEAR)) {
296  throw SerialIOException("failure during ::EscapeCommFunction()");
297  }
298 }
299 
300 void Serial::SerialImpl::flushOutput() const {
301  if (!is_open_) {
303  }
304  if (!::PurgeComm(fd_, PURGE_TXCLEAR)) {
305  throw SerialIOException("failure during ::EscapeCommFunction()");
306  }
307 }
308 
309 void Serial::SerialImpl::sendBreak(int duration_ms) const {
310  throw SerialException("sendBreak() is not implemented on Windows");
311 }
312 
313 void Serial::SerialImpl::setBreak(bool level) const {
314  setModemStatus(level ? SETBREAK : CLRBREAK);
315 }
316 
317 void Serial::SerialImpl::setModemStatus(uint32_t request, uint32_t command) const {
318  if (!is_open_) {
320  }
321  if (!::EscapeCommFunction(fd_, request)) {
322  throw SerialIOException("failure during ::EscapeCommFunction()");
323  }
324 }
325 
326 void Serial::SerialImpl::setRTS(bool level) const {
327  setModemStatus(level ? SETRTS : CLRRTS);
328 }
329 
330 void Serial::SerialImpl::setDTR(bool level) const {
331  setModemStatus(level ? SETDTR : CLRDTR);
332 }
333 
335  if (!is_open_) {
337  }
338  if (!::SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) {
339  throw SerialIOException("failure during ::SetCommMask()");
340  }
341  DWORD event;
342  if (!::WaitCommEvent(fd_, &event, nullptr)) {
343  throw SerialIOException("failure during ::WaitCommEvent()");
344  }
345 }
346 
347 uint32_t Serial::SerialImpl::getModemStatus() const {
348  if (!is_open_) {
350  }
351  DWORD modem_status;
352  if (!::GetCommModemStatus(fd_, &modem_status)) {
353  throw SerialIOException("failure during ::GetCommModemStatus()");
354  }
355  return modem_status;
356 }
357 
358 bool Serial::SerialImpl::getCTS() const {
359  return getModemStatus() & MS_CTS_ON;
360 }
361 
362 bool Serial::SerialImpl::getDSR() const {
363  return getModemStatus() & MS_DSR_ON;
364 }
365 
366 bool Serial::SerialImpl::getRI() const {
367  return getModemStatus() & MS_RING_ON;
368 }
369 
370 bool Serial::SerialImpl::getCD() const {
371  return getModemStatus() & MS_RLSD_ON;
372 }
373 
374 #endif // defined(_WIN32)
serial::parity_t
parity_t
Definition: serial.h:68
serial::parity_mark
@ parity_mark
Definition: serial.h:74
serial::Serial::SerialImpl::flushOutput
void flushOutput() const
Definition: impl_unix.cpp:560
serial::SerialIOException
Definition: serial.h:594
INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE
Definition: qbrobotics_research_api_wrapper.h:69
serial
Definition: impl.h:56
serial::Serial::SerialImpl::setPort
void setPort(const std::string &port)
Definition: impl_unix.cpp:471
serial::Serial::SerialImpl::waitByteTimes
void waitByteTimes(size_t count) const
Definition: impl_unix.cpp:407
serial::Serial::SerialImpl::sendBreak
void sendBreak(int duration_ms) const
Definition: impl_unix.cpp:569
serial::Serial::SerialImpl::open
void open()
Definition: impl_unix.cpp:48
serial::Serial::SerialImpl::getStopbits
stopbits_t getStopbits() const
Definition: impl_unix.cpp:527
serial::Serial::SerialImpl::getPort
std::string getPort() const
Definition: impl_unix.cpp:475
serial::Serial::Timeout
Definition: serial.h:101
serial::Serial::SerialImpl::setBaudrate
void setBaudrate(unsigned long baudrate)
Definition: impl_unix.cpp:487
serial::Serial::close
void close()
Definition: serial.cpp:41
serial::Serial::SerialImpl::setDTR
void setDTR(bool level) const
Definition: impl_unix.cpp:595
serial::Serial::SerialImpl::waitReadable
bool waitReadable(std::chrono::milliseconds timeout_ms) const
Definition: impl_unix.cpp:393
serial::stopbits_one
@ stopbits_one
Definition: serial.h:82
serial::Serial::SerialImpl::reconfigurePort
void reconfigurePort()
Definition: impl_unix.cpp:80
serial::Serial::SerialImpl::setBytesize
void setBytesize(bytesize_t bytesize)
Definition: impl_unix.cpp:498
impl.h
serial::flowcontrol_software
@ flowcontrol_software
Definition: serial.h:92
serial::parity_even
@ parity_even
Definition: serial.h:73
serial::Serial::SerialImpl::flush
void flush() const
Definition: impl_unix.cpp:542
serial::Serial::SerialImpl::setModemStatus
void setModemStatus(uint32_t request, uint32_t command=0) const
Definition: impl_unix.cpp:582
serial::Serial::SerialImpl::getBaudrate
unsigned long getBaudrate() const
Definition: impl_unix.cpp:494
serial::Serial::SerialImpl::read
size_t read(uint8_t *buf, size_t size=1)
Definition: impl_unix.cpp:415
serial::Serial::SerialImpl::getTimeout
Timeout getTimeout() const
Definition: impl_unix.cpp:483
serial::bytesize_t
bytesize_t
Definition: serial.h:58
serial::Serial::SerialImpl::setRTS
void setRTS(bool level) const
Definition: impl_unix.cpp:591
serial::Serial::SerialImpl::getCD
bool getCD() const
Definition: impl_unix.cpp:636
serial::Serial::SerialImpl::setFlowcontrol
void setFlowcontrol(flowcontrol_t flowcontrol)
Definition: impl_unix.cpp:531
serial::SerialInvalidArgumentException
Definition: serial.h:588
serial::Serial::SerialImpl::available
size_t available() const
Definition: impl_unix.cpp:371
serial::Serial::SerialImpl::waitWritable
bool waitWritable(std::chrono::milliseconds timeout_ms) const
Definition: impl_unix.cpp:400
serial::Serial::SerialImpl::getModemStatus
uint32_t getModemStatus() const
Definition: impl_unix.cpp:613
serial::Serial::SerialImpl::getCTS
bool getCTS() const
Definition: impl_unix.cpp:624
serial::Serial::SerialImpl::setParity
void setParity(parity_t parity)
Definition: impl_unix.cpp:509
serial::Serial::SerialImpl::setBreak
void setBreak(bool level) const
Definition: impl_unix.cpp:578
serial::Serial::SerialImpl::close
void close()
Definition: impl_unix.cpp:359
serial::Serial::SerialImpl::setStopbits
void setStopbits(stopbits_t stopbits)
Definition: impl_unix.cpp:520
serial::Serial::SerialImpl::getDSR
bool getDSR() const
Definition: impl_unix.cpp:628
serial::parity_odd
@ parity_odd
Definition: serial.h:72
start
ROSCPP_DECL void start()
serial::Serial::SerialImpl::write
size_t write(const uint8_t *data, size_t size)
Definition: impl_unix.cpp:446
serial::Serial::SerialImpl::port_
std::string port_
Definition: impl.h:197
serial::Serial::SerialImpl::getBytesize
bytesize_t getBytesize() const
Definition: impl_unix.cpp:505
serial::Serial::SerialImpl::~SerialImpl
virtual ~SerialImpl()
Definition: impl_unix.cpp:44
serial::flowcontrol_t
flowcontrol_t
Definition: serial.h:88
serial::sevenbits
@ sevenbits
Definition: serial.h:82
serial::Serial::SerialImpl::SerialImpl
SerialImpl(std::string port, unsigned long baudrate, Timeout timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol)
Definition: impl_unix.cpp:28
std
serial::Serial::SerialImpl::getRI
bool getRI() const
Definition: impl_unix.cpp:632
serial::Serial::SerialImpl::getParity
parity_t getParity() const
Definition: impl_unix.cpp:516
serial::stopbits_one_point_five
@ stopbits_one_point_five
Definition: serial.h:84
serial::parity_space
@ parity_space
Definition: serial.h:75
serial::stopbits_t
stopbits_t
Definition: serial.h:79
serial::flowcontrol_none
@ flowcontrol_none
Definition: serial.h:91
serial::SerialPortNotOpenException
Definition: serial.h:601
serial::flowcontrol_hardware
@ flowcontrol_hardware
Definition: serial.h:93
serial::Serial::SerialImpl::waitForModemChanges
void waitForModemChanges() const
Definition: impl_unix.cpp:599
serial::Serial::SerialImpl::getFlowcontrol
flowcontrol_t getFlowcontrol() const
Definition: impl_unix.cpp:538
serial::fivebits
@ fivebits
Definition: serial.h:80
serial::SerialException
Definition: serial.h:582
serial::parity_none
@ parity_none
Definition: serial.h:71
serial::Serial::SerialImpl::flushInput
void flushInput() const
Definition: impl_unix.cpp:551
serial::stopbits_two
@ stopbits_two
Definition: serial.h:83
serial::Serial::SerialImpl::isOpen
bool isOpen() const
Definition: impl_unix.cpp:367
serial::sixbits
@ sixbits
Definition: serial.h:81
serial::Serial::SerialImpl::setTimeout
void setTimeout(const Timeout &timeout)
Definition: impl_unix.cpp:479
serial::eightbits
@ eightbits
Definition: serial.h:83


qb_device_driver
Author(s): qbroboticsĀ®
autogenerated on Thu Apr 27 2023 02:36:32