MRPT  1.9.9
win32/net_serial.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://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 <windows.h>
35 
36 #include "net_serial.h"
37 #include "sdkcommon.h"
38 
39 namespace rp
40 {
41 namespace arch
42 {
43 namespace net
44 {
46  : rp::hal::serial_rxtx(), _serial_handle(nullptr), _baudrate(0), _flags(0)
47 {
48  _init();
49 }
50 
52 {
53  close();
54 
55  CloseHandle(_ro.hEvent);
56  CloseHandle(_wo.hEvent);
57  CloseHandle(_wait_o.hEvent);
58 }
59 
60 bool raw_serial::open() { return open(_portName, _baudrate, _flags); }
61 bool raw_serial::bind(const char* portname, _u32 baudrate, _u32 flags)
62 {
63  strncpy(_portName, portname, sizeof(_portName));
64  _baudrate = baudrate;
65  _flags = flags;
66  return true;
67 }
68 
69 bool raw_serial::open(const char* portname, _u32 baudrate, _u32 flags)
70 {
71  if (isOpened()) close();
72 
73  _serial_handle = CreateFileA(
74  portname, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING,
75  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
76 
77  if (_serial_handle == INVALID_HANDLE_VALUE) return false;
78 
79  if (!SetupComm(
81  {
82  close();
83  return false;
84  }
85 
86  _dcb.BaudRate = baudrate;
87  _dcb.ByteSize = 8;
88  _dcb.Parity = NOPARITY;
89  _dcb.StopBits = ONESTOPBIT;
90  _dcb.fDtrControl = DTR_CONTROL_ENABLE;
91 
92  if (!SetCommState(_serial_handle, &_dcb))
93  {
94  close();
95  return false;
96  }
97 
98  if (!SetCommTimeouts(_serial_handle, &_co))
99  {
100  close();
101  return false;
102  }
103 
104  if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR))
105  {
106  close();
107  return false;
108  }
109 
110  if (!PurgeComm(
112  PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
113  {
114  close();
115  return false;
116  }
117 
118  Sleep(30);
119  _is_serial_opened = true;
120 
121  // Clear the DTR bit set DTR=high
122  clearDTR();
123 
124  return true;
125 }
126 
127 void raw_serial::close()
128 {
129  SetCommMask(_serial_handle, 0);
130  ResetEvent(_wait_o.hEvent);
131 
132  CloseHandle(_serial_handle);
133  _serial_handle = INVALID_HANDLE_VALUE;
134 
135  _is_serial_opened = false;
136 }
137 
138 int raw_serial::senddata(const unsigned char* data, size_t size)
139 {
140  DWORD error;
141  DWORD w_len = 0, o_len = -1;
142  if (!isOpened()) return ANS_DEV_ERR;
143 
144  if (data == nullptr || size == 0) return 0;
145 
146  if (ClearCommError(_serial_handle, &error, nullptr) && error > 0)
147  PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR);
148 
149  if (!WriteFile(_serial_handle, data, size, &w_len, &_wo))
150  if (GetLastError() != ERROR_IO_PENDING) w_len = ANS_DEV_ERR;
151 
152  return w_len;
153 }
154 
155 int raw_serial::recvdata(unsigned char* data, size_t size)
156 {
157  if (!isOpened()) return 0;
158  DWORD r_len = 0;
159 
160  if (!ReadFile(_serial_handle, data, size, &r_len, &_ro))
161  {
162  if (GetLastError() == ERROR_IO_PENDING)
163  {
164  if (!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
165  {
166  if (GetLastError() != ERROR_IO_INCOMPLETE) r_len = 0;
167  }
168  }
169  else
170  r_len = 0;
171  }
172 
173  return r_len;
174 }
175 
176 void raw_serial::flush(_u32 flags)
177 {
178  PurgeComm(
180  PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
181 }
182 
183 int raw_serial::waitforsent(_u32 timeout, size_t* returned_size)
184 {
185  if (!isOpened()) return ANS_DEV_ERR;
186  DWORD w_len = 0;
187  _word_size_t ans = 0;
188 
189  if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT)
190  {
191  ans = ANS_TIMEOUT;
192  goto _final;
193  }
194  if (!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE))
195  {
196  ans = ANS_DEV_ERR;
197  }
198 _final:
199  if (returned_size) *returned_size = w_len;
200  return ans;
201 }
202 
203 int raw_serial::waitforrecv(_u32 timeout, size_t* returned_size)
204 {
205  if (!isOpened()) return -1;
206  DWORD r_len = 0;
207  _word_size_t ans = 0;
208 
209  if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT)
210  {
211  ans = ANS_TIMEOUT;
212  }
213  if (!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
214  {
215  ans = ANS_DEV_ERR;
216  }
217  if (returned_size) *returned_size = r_len;
218  return ans;
219 }
220 
222  size_t data_count, _u32 timeout, size_t* returned_size)
223 {
224  COMSTAT stat;
225  DWORD error;
226  DWORD msk, length;
227  size_t dummy_length;
228 
229  if (returned_size == nullptr) returned_size = (size_t*)&dummy_length;
230 
231  if (isOpened())
232  {
233  size_t rxqueue_remaining = rxqueue_count();
234  if (rxqueue_remaining >= data_count)
235  {
236  *returned_size = rxqueue_remaining;
237  return 0;
238  }
239  }
240 
241  while (isOpened())
242  {
243  msk = 0;
244  SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR);
245  if (!WaitCommEvent(_serial_handle, &msk, &_wait_o))
246  {
247  if (GetLastError() == ERROR_IO_PENDING)
248  {
249  if (WaitForSingleObject(_wait_o.hEvent, timeout) ==
250  WAIT_TIMEOUT)
251  {
252  *returned_size = 0;
253  return ANS_TIMEOUT;
254  }
255 
256  GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE);
257 
258  ::ResetEvent(_wait_o.hEvent);
259  }
260  else
261  {
262  ClearCommError(_serial_handle, &error, &stat);
263  *returned_size = stat.cbInQue;
264  return ANS_DEV_ERR;
265  }
266  }
267 
268  if (msk & EV_ERR)
269  {
270  // FIXME: may cause problem here
271  ClearCommError(_serial_handle, &error, &stat);
272  }
273 
274  if (msk & EV_RXCHAR)
275  {
276  ClearCommError(_serial_handle, &error, &stat);
277  if (stat.cbInQue >= data_count)
278  {
279  *returned_size = stat.cbInQue;
280  return 0;
281  }
282  }
283  }
284  *returned_size = 0;
285  return ANS_DEV_ERR;
286 }
287 
289 {
290  if (!isOpened()) return 0;
291  COMSTAT com_stat;
292  DWORD error;
293  DWORD r_len = 0;
294 
295  if (ClearCommError(_serial_handle, &error, &com_stat) && error > 0)
296  {
297  PurgeComm(_serial_handle, PURGE_RXABORT | PURGE_RXCLEAR);
298  return 0;
299  }
300  return com_stat.cbInQue;
301 }
302 
303 void raw_serial::setDTR()
304 {
305  if (!isOpened()) return;
306 
307  EscapeCommFunction(_serial_handle, SETDTR);
308 }
309 
311 {
312  if (!isOpened()) return;
313 
314  EscapeCommFunction(_serial_handle, CLRDTR);
315 }
316 
317 void raw_serial::_init()
318 {
319  memset(&_dcb, 0, sizeof(_dcb));
320  _dcb.DCBlength = sizeof(_dcb);
321  _serial_handle = INVALID_HANDLE_VALUE;
322  memset(&_co, 0, sizeof(_co));
323  _co.ReadIntervalTimeout = 0;
324  _co.ReadTotalTimeoutMultiplier = 0;
325  _co.ReadTotalTimeoutConstant = 0;
326  _co.WriteTotalTimeoutMultiplier = 0;
327  _co.WriteTotalTimeoutConstant = 0;
328 
329  memset(&_ro, 0, sizeof(_ro));
330  memset(&_wo, 0, sizeof(_wo));
331  memset(&_wait_o, 0, sizeof(_wait_o));
332 
333  _ro.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
334  _wo.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
335  _wait_o.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
336 
337  _portName[0] = 0;
338 }
339 } // namespace net
340 } // namespace arch
341 } // namespace rp
342 
343 // begin rp::hal
344 namespace rp
345 {
346 namespace hal
347 {
348 serial_rxtx* serial_rxtx::CreateRxTx()
349 {
350  return new rp::arch::net::raw_serial();
351 }
352 
353 void serial_rxtx::ReleaseRxTx(serial_rxtx* rxtx) { delete rxtx; }
354 } // namespace hal
355 } // namespace rp
size_t rxqueue_count() override
virtual bool isOpened()
Definition: abs_rxtx.h:78
bool bind(const char *portname, uint32_t baudrate, uint32_t flags=0) override
static serial_rxtx * CreateRxTx()
static void ReleaseRxTx(serial_rxtx *)
volatile bool _is_serial_opened
Definition: abs_rxtx.h:81
int waitforsent(_u32 timeout=-1, size_t *returned_size=nullptr) override
int waitfordata(size_t data_count, _u32 timeout=-1, size_t *returned_size=nullptr) override
int senddata(const unsigned char *data, size_t size) override
void flush(_u32 flags) override
#define FALSE
Definition: xmlParser.h:230
GLuint GLsizei GLsizei * length
Definition: glext.h:4079
uint32_t _u32
Definition: rptypes.h:69
int waitforrecv(_u32 timeout=-1, size_t *returned_size=nullptr) override
volatile HANDLE _serial_handle
GLsizeiptr size
Definition: glext.h:3934
#define TRUE
Definition: xmlParser.h:233
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3550
int recvdata(unsigned char *data, size_t size) override



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019