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


rplidar_ros
Author(s):
autogenerated on Fri Aug 2 2024 08:42:14