Main MRPT website > C++ reference for MRPT 1.5.7
macOS/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/macOS/arch_macOS.h"
36 #include "arch/macOS/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 
51 raw_serial::~raw_serial()
52 {
53  close();
54 
55 }
56 
57 bool raw_serial::open()
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 */
120  if (tcsetattr(serial_fd, TCSANOW, &options))
121  {
122  close();
123  return false;
124  }
125 
126  _is_serial_opened = true;
127 
128  //Clear the DTR bit to let the motor spin
129  clearDTR();
130 
131  return true;
132 }
133 
134 void raw_serial::close()
135 {
136  if (serial_fd != -1)
137  ::close(serial_fd);
138  serial_fd = -1;
139 
140  _is_serial_opened = false;
141 }
142 
143 int raw_serial::senddata(const unsigned char * data, _word_size_t size)
144 {
145 // FIXME: non-block io should be used
146  if (!isOpened()) return 0;
147 
148  if (data == NULL || size ==0) return 0;
149 
150  size_t tx_len = 0;
151  required_tx_cnt = 0;
152  do {
153  int ans = ::write(serial_fd, data + tx_len, size-tx_len);
154 
155  if (ans == -1) return tx_len;
156 
157  tx_len += ans;
158  required_tx_cnt = tx_len;
159  }while (tx_len<size);
160 
161 
162  return tx_len;
163 }
164 
165 
166 
167 int raw_serial::recvdata(unsigned char * data, _word_size_t size)
168 {
169  if (!isOpened()) return 0;
170 
171  int ans = ::read(serial_fd, data, size);
172 
173  if (ans == -1) ans=0;
174  required_rx_cnt = ans;
175  return ans;
176 }
177 
178 
179 void raw_serial::flush( _u32 flags)
180 {
181  tcflush(serial_fd,TCIFLUSH);
182 }
183 
184 int raw_serial::waitforsent(_u32 timeout, _word_size_t * returned_size)
185 {
186  if (returned_size) *returned_size = required_tx_cnt;
187  return 0;
188 }
189 
190 int raw_serial::waitforrecv(_u32 timeout, _word_size_t * returned_size)
191 {
192  if (!isOpened() ) return -1;
193 
194  if (returned_size) *returned_size = required_rx_cnt;
195  return 0;
196 }
197 
198 int raw_serial::waitfordata(_word_size_t data_count, _u32 timeout, _word_size_t * returned_size)
199 {
200  _word_size_t length = 0;
201  if (returned_size==NULL) returned_size=(_word_size_t *)&length;
202  *returned_size = 0;
203 
204  int max_fd;
205  fd_set input_set;
206  struct timeval timeout_val;
207 
208  /* Initialize the input set */
209  FD_ZERO(&input_set);
210  FD_SET(serial_fd, &input_set);
211  max_fd = serial_fd + 1;
212 
213  /* Initialize the timeout structure */
214  timeout_val.tv_sec = timeout / 1000;
215  timeout_val.tv_usec = (timeout % 1000) * 1000;
216 
217  if ( isOpened() )
218  {
219  if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
220  if (*returned_size >= data_count)
221  {
222  return 0;
223  }
224  }
225 
226  while ( isOpened() )
227  {
228  /* Do the select */
229  int n = ::select(max_fd, &input_set, NULL, NULL, &timeout_val);
230 
231  if (n < 0)
232  {
233  // select error
234  return ANS_DEV_ERR;
235  }
236  else if (n == 0)
237  {
238  // time out
239  return ANS_TIMEOUT;
240  }
241  else
242  {
243  // data avaliable
244  assert (FD_ISSET(serial_fd, &input_set));
245 
246 
247  if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
248  if (*returned_size >= data_count)
249  {
250  return 0;
251  }
252  else
253  {
254  int remain_timeout = timeout_val.tv_sec*1000000 + timeout_val.tv_usec;
255  int expect_remain_time = (data_count - *returned_size)*1000000*8/_baudrate;
256  if (remain_timeout > expect_remain_time)
257  usleep(expect_remain_time);
258  }
259  }
260 
261  }
262  return ANS_DEV_ERR;
263 }
264 
265 size_t raw_serial::rxqueue_count()
266 {
267  if ( !isOpened() ) return 0;
268  size_t remaining;
269 
270  if (::ioctl(serial_fd, FIONREAD, &remaining) == -1) return 0;
271  return remaining;
272 }
273 
274 void raw_serial::setDTR()
275 {
276  if ( !isOpened() ) return;
277 
278  uint32_t dtr_bit = TIOCM_DTR;
279  ioctl(serial_fd, TIOCMBIS, &dtr_bit);
280 }
281 
282 void raw_serial::clearDTR()
283 {
284  if ( !isOpened() ) return;
285 
286  uint32_t dtr_bit = TIOCM_DTR;
287  ioctl(serial_fd, TIOCMBIC, &dtr_bit);
288 }
289 
290 void raw_serial::_init()
291 {
292  serial_fd = 0;
293  _portName[0] = 0;
294  required_tx_cnt = required_rx_cnt = 0;
295 }
296 
297 
298 
299 _u32 raw_serial::getTermBaudBitmap(_u32 baud)
300 {
301 #define BAUD_CONV(_baud_) case _baud_: return _baud_
302  switch (baud)
303  {
304  BAUD_CONV(1200);
305  BAUD_CONV(1800);
306  BAUD_CONV(2400);
307  BAUD_CONV(4800);
308  BAUD_CONV(9600);
309  BAUD_CONV(19200);
310  BAUD_CONV(38400);
311  BAUD_CONV(57600);
312  BAUD_CONV(115200);
313  BAUD_CONV(230400);
314  BAUD_CONV(460800);
315  BAUD_CONV(500000);
316  BAUD_CONV(576000);
317  BAUD_CONV(921600);
318  BAUD_CONV(1000000);
319  BAUD_CONV(1152000);
320  BAUD_CONV(1500000);
321  BAUD_CONV(2000000);
322  BAUD_CONV(2500000);
323  BAUD_CONV(3000000);
324  BAUD_CONV(3500000);
325  BAUD_CONV(4000000);
326  }
327  return -1;
328 }
329 
330 }}} //end rp::arch::net
331 
332 
333 
334 //begin rp::hal
335 namespace rp{ namespace hal{
336 
337  serial_rxtx * serial_rxtx::CreateRxTx()
338  {
339  return new rp::arch::net::raw_serial();
340  }
341 
342  void serial_rxtx::ReleaseRxTx(serial_rxtx *rxtx)
343  {
344  delete rxtx;
345  }
346 
347 }} //end rp::hal
GLenum GLsizei n
Definition: glext.h:4618
#define BAUD_CONV(_baud_)
static serial_rxtx * CreateRxTx()
static void ReleaseRxTx(serial_rxtx *)
typedef _word_size_t(THREAD_PROC *thread_proc_t)(void *)
GLuint GLsizei GLsizei * length
Definition: glext.h:3900
uint32_t _u32
Definition: rptypes.h:69
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