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