Main MRPT website > C++ reference for MRPT 1.9.9
win32/net_serial.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 /*
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #include "sdkcommon.h"
35 #include "net_serial.h"
36 
37 namespace rp
38 {
39 namespace arch
40 {
41 namespace net
42 {
44  : rp::hal::serial_rxtx(), _serial_handle(nullptr), _baudrate(0), _flags(0)
45 {
46  _init();
47 }
48 
50 {
51  close();
52 
53  CloseHandle(_ro.hEvent);
54  CloseHandle(_wo.hEvent);
55  CloseHandle(_wait_o.hEvent);
56 }
57 
58 bool raw_serial::open() { return open(_portName, _baudrate, _flags); }
59 bool raw_serial::bind(const char* portname, _u32 baudrate, _u32 flags)
60 {
61  strncpy(_portName, portname, sizeof(_portName));
62  _baudrate = baudrate;
63  _flags = flags;
64  return true;
65 }
66 
67 bool raw_serial::open(const char* portname, _u32 baudrate, _u32 flags)
68 {
69  if (isOpened()) close();
70 
71  _serial_handle = CreateFileA(
72  portname, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING,
73  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
74 
75  if (_serial_handle == INVALID_HANDLE_VALUE) return false;
76 
77  if (!SetupComm(
79  {
80  close();
81  return false;
82  }
83 
84  _dcb.BaudRate = baudrate;
85  _dcb.ByteSize = 8;
86  _dcb.Parity = NOPARITY;
87  _dcb.StopBits = ONESTOPBIT;
88  _dcb.fDtrControl = DTR_CONTROL_ENABLE;
89 
90  if (!SetCommState(_serial_handle, &_dcb))
91  {
92  close();
93  return false;
94  }
95 
96  if (!SetCommTimeouts(_serial_handle, &_co))
97  {
98  close();
99  return false;
100  }
101 
102  if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR))
103  {
104  close();
105  return false;
106  }
107 
108  if (!PurgeComm(
110  PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
111  {
112  close();
113  return false;
114  }
115 
116  Sleep(30);
117  _is_serial_opened = true;
118 
119  // Clear the DTR bit set DTR=high
120  clearDTR();
121 
122  return true;
123 }
124 
125 void raw_serial::close()
126 {
127  SetCommMask(_serial_handle, 0);
128  ResetEvent(_wait_o.hEvent);
129 
130  CloseHandle(_serial_handle);
131  _serial_handle = INVALID_HANDLE_VALUE;
132 
133  _is_serial_opened = false;
134 }
135 
136 int raw_serial::senddata(const unsigned char* data, size_t size)
137 {
138  DWORD error;
139  DWORD w_len = 0, o_len = -1;
140  if (!isOpened()) return ANS_DEV_ERR;
141 
142  if (data == nullptr || size == 0) return 0;
143 
144  if (ClearCommError(_serial_handle, &error, nullptr) && error > 0)
145  PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR);
146 
147  if (!WriteFile(_serial_handle, data, size, &w_len, &_wo))
148  if (GetLastError() != ERROR_IO_PENDING) w_len = ANS_DEV_ERR;
149 
150  return w_len;
151 }
152 
153 int raw_serial::recvdata(unsigned char* data, size_t size)
154 {
155  if (!isOpened()) return 0;
156  DWORD r_len = 0;
157 
158  if (!ReadFile(_serial_handle, data, size, &r_len, &_ro))
159  {
160  if (GetLastError() == ERROR_IO_PENDING)
161  {
162  if (!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
163  {
164  if (GetLastError() != ERROR_IO_INCOMPLETE) r_len = 0;
165  }
166  }
167  else
168  r_len = 0;
169  }
170 
171  return r_len;
172 }
173 
174 void raw_serial::flush(_u32 flags)
175 {
176  PurgeComm(
178  PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
179 }
180 
181 int raw_serial::waitforsent(_u32 timeout, size_t* returned_size)
182 {
183  if (!isOpened()) return ANS_DEV_ERR;
184  DWORD w_len = 0;
185  _word_size_t ans = 0;
186 
187  if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT)
188  {
189  ans = ANS_TIMEOUT;
190  goto _final;
191  }
192  if (!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE))
193  {
194  ans = ANS_DEV_ERR;
195  }
196 _final:
197  if (returned_size) *returned_size = w_len;
198  return ans;
199 }
200 
201 int raw_serial::waitforrecv(_u32 timeout, size_t* returned_size)
202 {
203  if (!isOpened()) return -1;
204  DWORD r_len = 0;
205  _word_size_t ans = 0;
206 
207  if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT)
208  {
209  ans = ANS_TIMEOUT;
210  }
211  if (!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
212  {
213  ans = ANS_DEV_ERR;
214  }
215  if (returned_size) *returned_size = r_len;
216  return ans;
217 }
218 
220  size_t data_count, _u32 timeout, size_t* returned_size)
221 {
222  COMSTAT stat;
223  DWORD error;
224  DWORD msk, length;
225  size_t dummy_length;
226 
227  if (returned_size == nullptr) returned_size = (size_t*)&dummy_length;
228 
229  if (isOpened())
230  {
231  size_t rxqueue_remaining = rxqueue_count();
232  if (rxqueue_remaining >= data_count)
233  {
234  *returned_size = rxqueue_remaining;
235  return 0;
236  }
237  }
238 
239  while (isOpened())
240  {
241  msk = 0;
242  SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR);
243  if (!WaitCommEvent(_serial_handle, &msk, &_wait_o))
244  {
245  if (GetLastError() == ERROR_IO_PENDING)
246  {
247  if (WaitForSingleObject(_wait_o.hEvent, timeout) ==
248  WAIT_TIMEOUT)
249  {
250  *returned_size = 0;
251  return ANS_TIMEOUT;
252  }
253 
254  GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE);
255 
256  ::ResetEvent(_wait_o.hEvent);
257  }
258  else
259  {
260  ClearCommError(_serial_handle, &error, &stat);
261  *returned_size = stat.cbInQue;
262  return ANS_DEV_ERR;
263  }
264  }
265 
266  if (msk & EV_ERR)
267  {
268  // FIXME: may cause problem here
269  ClearCommError(_serial_handle, &error, &stat);
270  }
271 
272  if (msk & EV_RXCHAR)
273  {
274  ClearCommError(_serial_handle, &error, &stat);
275  if (stat.cbInQue >= data_count)
276  {
277  *returned_size = stat.cbInQue;
278  return 0;
279  }
280  }
281  }
282  *returned_size = 0;
283  return ANS_DEV_ERR;
284 }
285 
287 {
288  if (!isOpened()) return 0;
289  COMSTAT com_stat;
290  DWORD error;
291  DWORD r_len = 0;
292 
293  if (ClearCommError(_serial_handle, &error, &com_stat) && error > 0)
294  {
295  PurgeComm(_serial_handle, PURGE_RXABORT | PURGE_RXCLEAR);
296  return 0;
297  }
298  return com_stat.cbInQue;
299 }
300 
301 void raw_serial::setDTR()
302 {
303  if (!isOpened()) return;
304 
305  EscapeCommFunction(_serial_handle, SETDTR);
306 }
307 
309 {
310  if (!isOpened()) return;
311 
312  EscapeCommFunction(_serial_handle, CLRDTR);
313 }
314 
315 void raw_serial::_init()
316 {
317  memset(&_dcb, 0, sizeof(_dcb));
318  _dcb.DCBlength = sizeof(_dcb);
319  _serial_handle = INVALID_HANDLE_VALUE;
320  memset(&_co, 0, sizeof(_co));
321  _co.ReadIntervalTimeout = 0;
322  _co.ReadTotalTimeoutMultiplier = 0;
323  _co.ReadTotalTimeoutConstant = 0;
324  _co.WriteTotalTimeoutMultiplier = 0;
325  _co.WriteTotalTimeoutConstant = 0;
326 
327  memset(&_ro, 0, sizeof(_ro));
328  memset(&_wo, 0, sizeof(_wo));
329  memset(&_wait_o, 0, sizeof(_wait_o));
330 
331  _ro.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
332  _wo.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
333  _wait_o.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
334 
335  _portName[0] = 0;
336 }
337 }
338 }
339 } // end rp::arch::net
340 
341 // begin rp::hal
342 namespace rp
343 {
344 namespace hal
345 {
346 serial_rxtx* serial_rxtx::CreateRxTx()
347 {
348  return new rp::arch::net::raw_serial();
349 }
350 
351 void serial_rxtx::ReleaseRxTx(serial_rxtx* rxtx) { delete rxtx; }
352 }
353 } // end rp::hal
sdkcommon.h
rp::arch::net::raw_serial::_wait_o
OVERLAPPED _wait_o
Definition: win32/net_serial.h:85
rp::arch::net::raw_serial::~raw_serial
virtual ~raw_serial()
Definition: linux/net_serial.cpp:51
rp::hal::serial_rxtx::ReleaseRxTx
static void ReleaseRxTx(serial_rxtx *)
Definition: linux/net_serial.cpp:324
rp::arch::net::raw_serial::_co
COMMTIMEOUTS _co
Definition: win32/net_serial.h:88
net_serial.h
rp::arch::net::raw_serial::waitforrecv
virtual int waitforrecv(_u32 timeout=-1, size_t *returned_size=nullptr)
Definition: linux/net_serial.cpp:172
rp::arch::net::raw_serial::_baudrate
uint32_t _baudrate
Definition: linux/net_serial.h:82
rp::arch::net::raw_serial::_wo
OVERLAPPED _wo
Definition: win32/net_serial.h:84
rp::arch::net::raw_serial::rxqueue_count
virtual size_t rxqueue_count()
Definition: linux/net_serial.cpp:250
rp::hal::serial_rxtx::isOpened
virtual bool isOpened()
Definition: abs_rxtx.h:80
rp::hal::serial_rxtx::ANS_TIMEOUT
@ ANS_TIMEOUT
Definition: abs_rxtx.h:48
rp::hal::serial_rxtx::ANS_DEV_ERR
@ ANS_DEV_ERR
Definition: abs_rxtx.h:49
rp::arch::net::raw_serial::_init
void _init()
Definition: linux/net_serial.cpp:275
rp::hal::serial_rxtx::CreateRxTx
static serial_rxtx * CreateRxTx()
Definition: linux/net_serial.cpp:319
TRUE
#define TRUE
Definition: xmlParser.h:234
rp::arch::net::raw_serial::_portName
char _portName[200]
Definition: linux/net_serial.h:81
length
GLuint GLsizei GLsizei * length
Definition: glext.h:4064
mrpt::obs::gnss::error
uint32_t error
Definition: gnss_messages_novatel.h:330
rp::arch::net::raw_serial::SERIAL_RX_BUFFER_SIZE
@ SERIAL_RX_BUFFER_SIZE
Definition: linux/net_serial.h:49
rp::arch::net::raw_serial::open
virtual bool open()
Definition: linux/net_serial.cpp:52
data
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3547
rp::arch::net::raw_serial::_ro
OVERLAPPED _ro
Definition: win32/net_serial.h:84
rp::arch::net::raw_serial::_flags
uint32_t _flags
Definition: linux/net_serial.h:83
rp::arch::net::raw_serial::senddata
virtual int senddata(const unsigned char *data, size_t size)
Definition: linux/net_serial.cpp:132
rp::arch::net::raw_serial::clearDTR
virtual void clearDTR()
Definition: linux/net_serial.cpp:267
rp::arch::net::raw_serial::_dcb
DCB _dcb
Definition: win32/net_serial.h:87
rp::arch::net::raw_serial::bind
virtual bool bind(const char *portname, uint32_t baudrate, uint32_t flags=0)
Definition: linux/net_serial.cpp:53
rp::arch::net::raw_serial::_serial_handle
volatile HANDLE _serial_handle
Definition: win32/net_serial.h:86
rp::arch::net::raw_serial::waitfordata
virtual int waitfordata(size_t data_count, _u32 timeout=-1, size_t *returned_size=nullptr)
Definition: linux/net_serial.cpp:180
rp::arch::net::raw_serial::close
virtual void close()
Definition: linux/net_serial.cpp:124
rp::arch::net::raw_serial::recvdata
virtual int recvdata(unsigned char *data, size_t size)
Definition: linux/net_serial.cpp:154
FALSE
#define FALSE
Definition: xmlParser.h:231
rp::arch::net::raw_serial::setDTR
virtual void setDTR()
Definition: linux/net_serial.cpp:259
rp::arch::net::raw_serial::flush
virtual void flush(_u32 flags)
Definition: linux/net_serial.cpp:165
rp::arch::net::raw_serial
Definition: linux/net_serial.h:44
rp::arch::net::raw_serial::waitforsent
virtual int waitforsent(_u32 timeout=-1, size_t *returned_size=nullptr)
Definition: linux/net_serial.cpp:166
rp
Definition: rplidar_driver.h:40
rp::arch::net::raw_serial::raw_serial
raw_serial()
Definition: linux/net_serial.cpp:45
_u32
uint32_t _u32
Definition: rptypes.h:66
size
GLsizeiptr size
Definition: glext.h:3923
rp::arch::net::raw_serial::SERIAL_TX_BUFFER_SIZE
@ SERIAL_TX_BUFFER_SIZE
Definition: linux/net_serial.h:50
rp::hal::serial_rxtx::_is_serial_opened
volatile bool _is_serial_opened
Definition: abs_rxtx.h:82



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST