Main MRPT website > C++ reference for MRPT 1.5.7
linux/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 - 2016 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 "arch/linux/arch_linux.h"
36 #include "arch/linux/net_serial.h"
37 #include <termios.h>
38 #include <sys/select.h>
39 
40 namespace rp{ namespace arch{ namespace net{
41 
43  : rp::hal::serial_rxtx()
44  , _baudrate(0)
45  , _flags(0)
46  , serial_fd(-1)
47 {
48  _init();
49 }
50 
52 {
53  close();
54 
55 }
56 
58 {
59  return open(_portName, _baudrate, _flags);
60 }
61 
62 bool raw_serial::bind(const char * portname, uint32_t baudrate, uint32_t flags)
63 {
64  strncpy(_portName, portname, sizeof(_portName));
65  _baudrate = baudrate;
66  _flags = flags;
67  return true;
68 }
69 
70 bool raw_serial::open(const char * portname, uint32_t baudrate, uint32_t flags)
71 {
72  if (isOpened()) close();
73 
74  serial_fd = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
75 
76  if (serial_fd == -1) return false;
77 
78  struct termios options, oldopt;
79  tcgetattr(serial_fd, &oldopt);
80  bzero(&options,sizeof(struct termios));
81 
82  _u32 termbaud = getTermBaudBitmap(baudrate);
83 
84  if (termbaud == (_u32)-1) {
85  close();
86  return false;
87  }
88  cfsetispeed(&options, termbaud);
89  cfsetospeed(&options, termbaud);
90 
91  // enable rx and tx
92  options.c_cflag |= (CLOCAL | CREAD);
93 
94 
95  options.c_cflag &= ~PARENB; //no checkbit
96  options.c_cflag &= ~CSTOPB; //1bit stop bit
97 
98  options.c_cflag &= ~CSIZE;
99  options.c_cflag |= CS8; /* Select 8 data bits */
100 
101 #ifdef CNEW_RTSCTS
102  options.c_cflag &= ~CNEW_RTSCTS; // no hw flow control
103 #endif
104 
105  options.c_iflag &= ~(IXON | IXOFF | IXANY); // no sw flow control
106 
107  // raw input mode
108  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
109  // raw output mode
110  options.c_oflag &= ~OPOST;
111 
112  tcflush(serial_fd,TCIFLUSH);
113 
114  if (fcntl(serial_fd, F_SETFL, FNDELAY))
115  {
116  close();
117  return false;
118  }
119  if (tcsetattr(serial_fd, TCSANOW, &options))
120  {
121  close();
122  return false;
123  }
124 
125  _is_serial_opened = true;
126 
127  //Clear the DTR bit to let the motor spin
128  clearDTR();
129 
130  return true;
131 }
132 
134 {
135  if (serial_fd != -1)
137  serial_fd = -1;
138 
139  _is_serial_opened = false;
140 }
141 
142 int raw_serial::senddata(const unsigned char * data, size_t size)
143 {
144 // FIXME: non-block io should be used
145  if (!isOpened()) return 0;
146 
147  if (data == NULL || size ==0) return 0;
148 
149  size_t tx_len = 0;
150  required_tx_cnt = 0;
151  do {
152  int ans = ::write(serial_fd, data + tx_len, size-tx_len);
153 
154  if (ans == -1) return tx_len;
155 
156  tx_len += ans;
157  required_tx_cnt = tx_len;
158  }while (tx_len<size);
159 
160 
161  return tx_len;
162 }
163 
164 
165 int raw_serial::recvdata(unsigned char * data, size_t size)
166 {
167  if (!isOpened()) return 0;
168 
169  int ans = ::read(serial_fd, data, size);
170 
171  if (ans == -1) ans=0;
172  required_rx_cnt = ans;
173  return ans;
174 }
175 
176 
178 {
179  tcflush(serial_fd,TCIFLUSH);
180 }
181 
182 int raw_serial::waitforsent(_u32 timeout, size_t * returned_size)
183 {
184  if (returned_size) *returned_size = required_tx_cnt;
185  return 0;
186 }
187 
188 int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size)
189 {
190  if (!isOpened() ) return -1;
191 
192  if (returned_size) *returned_size = required_rx_cnt;
193  return 0;
194 }
195 
196 int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
197 {
198  size_t length = 0;
199  if (returned_size==NULL) returned_size=(size_t *)&length;
200  *returned_size = 0;
201 
202  int max_fd;
203  fd_set input_set;
204  struct timeval timeout_val;
205 
206  /* Initialize the input set */
207  FD_ZERO(&input_set);
208  FD_SET(serial_fd, &input_set);
209  max_fd = serial_fd + 1;
210 
211  /* Initialize the timeout structure */
212  timeout_val.tv_sec = timeout / 1000;
213  timeout_val.tv_usec = (timeout % 1000) * 1000;
214 
215  if ( isOpened() )
216  {
217  if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
218  if (*returned_size >= data_count)
219  {
220  return 0;
221  }
222  }
223 
224  while ( isOpened() )
225  {
226  /* Do the select */
227  int n = ::select(max_fd, &input_set, NULL, NULL, &timeout_val);
228 
229  if (n < 0)
230  {
231  // select error
232  return ANS_DEV_ERR;
233  }
234  else if (n == 0)
235  {
236  // time out
237  return ANS_TIMEOUT;
238  }
239  else
240  {
241  // data avaliable
242  assert (FD_ISSET(serial_fd, &input_set));
243 
244 
245  if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
246  if (*returned_size >= data_count)
247  {
248  return 0;
249  }
250  else
251  {
252  int remain_timeout = timeout_val.tv_sec*1000000 + timeout_val.tv_usec;
253  int expect_remain_time = (data_count - *returned_size)*1000000*8/_baudrate;
254  if (remain_timeout > expect_remain_time)
255  usleep(expect_remain_time);
256  }
257  }
258 
259  }
260 
261  return ANS_DEV_ERR;
262 }
263 
265 {
266  if ( !isOpened() ) return 0;
267  size_t remaining;
268 
269  if (::ioctl(serial_fd, FIONREAD, &remaining) == -1) return 0;
270  return remaining;
271 }
272 
274 {
275  if ( !isOpened() ) return;
276 
277  uint32_t dtr_bit = TIOCM_DTR;
278  ioctl(serial_fd, TIOCMBIS, &dtr_bit);
279 }
280 
282 {
283  if ( !isOpened() ) return;
284 
285  uint32_t dtr_bit = TIOCM_DTR;
286  ioctl(serial_fd, TIOCMBIC, &dtr_bit);
287 }
288 
290 {
291  serial_fd = 0;
292  _portName[0] = 0;
294 }
295 
296 
297 
299 {
300 #define BAUD_CONV(_baud_) \
301  case _baud_: \
302  return B##_baud_
303  switch (baud)
304  {
305  BAUD_CONV(1200);
306  BAUD_CONV(1800);
307  BAUD_CONV(2400);
308  BAUD_CONV(4800);
309  BAUD_CONV(9600);
310  BAUD_CONV(19200);
311  BAUD_CONV(38400);
312  BAUD_CONV(57600);
313  BAUD_CONV(115200);
314  BAUD_CONV(230400);
315  BAUD_CONV(460800);
316  BAUD_CONV(500000);
317  BAUD_CONV(576000);
318  BAUD_CONV(921600);
319  BAUD_CONV(1000000);
320  BAUD_CONV(1152000);
321  BAUD_CONV(1500000);
322  BAUD_CONV(2000000);
323  }
324  return -1;
325 }
326 
327 }}} //end rp::arch::net
328 
329 //begin rp::hal
330 namespace rp{ namespace hal{
331 
333 {
334  return new rp::arch::net::raw_serial();
335 }
336 
338 {
339  delete rxtx;
340 }
341 
342 }} //end rp::hal
virtual void flush(_u32 flags)
virtual bool isOpened()
Definition: abs_rxtx.h:75
GLenum GLsizei n
Definition: glext.h:4618
virtual int waitfordata(size_t data_count, _u32 timeout=-1, size_t *returned_size=NULL)
virtual int waitforsent(_u32 timeout=-1, size_t *returned_size=NULL)
#define BAUD_CONV(_baud_)
static serial_rxtx * CreateRxTx()
static void ReleaseRxTx(serial_rxtx *)
volatile bool _is_serial_opened
Definition: abs_rxtx.h:81
virtual bool bind(const char *portname, uint32_t baudrate, uint32_t flags=0)
virtual int senddata(const unsigned char *data, size_t size)
virtual int recvdata(unsigned char *data, size_t size)
GLuint GLsizei GLsizei * length
Definition: glext.h:3900
uint32_t _u32
Definition: rptypes.h:69
virtual int waitforrecv(_u32 timeout=-1, size_t *returned_size=NULL)
GLsizeiptr size
Definition: glext.h:3779
unsigned __int32 uint32_t
Definition: rptypes.h:49
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3520



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019