Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpSerial.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Serial communication.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpConfig.h>
40 
41 #if !defined(_WIN32)
42 
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sys/stat.h>
48 #include <sys/types.h>
49 #include <sys/ioctl.h>
50 #include <termios.h>
51 #include <unistd.h>
52 #include <errno.h>
53 
54 #include <visp3/core/vpSerial.h>
55 #include <visp3/core/vpException.h>
56 
57 #ifndef TIOCINQ
58 # ifdef FIONREAD
59 # define TIOCINQ FIONREAD
60 # else
61 # define TIOCINQ 0x541B
62 # endif
63 #endif
64 
100 vpSerial::vpSerial(const std::string &port, unsigned long baudrate,
101  bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
102  flowcontrol_t flowcontrol)
103  : m_port(port), m_fd(-1), m_is_open(false), m_xonxoff(false), m_rtscts(false),
104  m_baudrate(baudrate), m_parity(parity),
105  m_bytesize(bytesize), m_stopbits(stopbits), m_flowcontrol(flowcontrol)
106 {
107  if (m_port.empty () == false)
108  open();
109 }
110 
115 {
116  close();
117 }
118 
123 void vpSerial::setBaudrate(const unsigned long baudrate)
124 {
125  m_baudrate = baudrate;
126 }
127 
132 void vpSerial::setBytesize(const bytesize_t &bytesize)
133 {
134  m_bytesize = bytesize;
135 }
136 
141 void vpSerial::setFlowcontrol(const flowcontrol_t &flowcontrol)
142 {
143  m_flowcontrol = flowcontrol;
144 }
145 
150 void vpSerial::setParity(const parity_t &parity)
151 {
152  m_parity = parity;
153 }
154 
159 void vpSerial::setStopbits(const stopbits_t &stopbits)
160 {
161  m_stopbits = stopbits;
162 }
163 
181 void vpSerial::setPort(const std::string &port)
182 {
183  m_port = port;
184 }
185 
190 {
191  if (!m_is_open) {
192  return 0;
193  }
194  int count = 0;
195  if (-1 == ioctl (m_fd, TIOCINQ, &count)) {
196  throw(vpException(vpException::fatalError, "Cannot check is serial port data available"));
197  } else {
198  return count;
199  }
200 }
201 
207 {
208  if (m_is_open == true) {
209  if (m_fd != -1) {
210  int ret;
211  ret = ::close (m_fd);
212  if (ret == 0) {
213  m_fd = -1;
214  } else {
215  throw(vpException(vpException::fatalError, "Cannot close serial port"));
216  }
217  }
218  m_is_open = false;
219  }
220 }
221 
250 {
251  if (m_port.empty ()) {
252  throw(vpException(vpException::fatalError, "Serial port empty"));
253  }
254  if (m_is_open == true) {
255  throw(vpException(vpException::fatalError, "Serial port already open"));
256  }
257 
258  m_fd = ::open (m_port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
259 
260  if (m_fd == -1) {
261  switch (errno) {
262  case EINTR:
263  // Try again because this is a recoverable error.
264  open();
265  return;
266  case ENFILE:
267  case EMFILE:
268  throw(vpException(vpException::fatalError, "Serial port has to many handles open"));
269  default:
270  throw(vpException(vpException::fatalError, "Serial port opening error"));
271  }
272  }
273 
274  configure();
275  m_is_open = true;
276 }
277 
284 bool vpSerial::read(char *c, long timeout_s)
285 {
286  if (m_is_open == false) {
287  throw(vpException(vpException::fatalError, "Serial port not opened"));
288  }
289 
290  fd_set readfds; /* list of fds for select to listen to */
291  struct timeval timeout = {timeout_s, 0}; // seconde, micro-sec
292 
293  FD_ZERO(&readfds);
294  FD_SET(static_cast<unsigned int>(m_fd), &readfds);
295 
296  int ret = select(FD_SETSIZE, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timeout);
297 
298  if (ret < 0) {
299  throw(vpException(vpException::fatalError, "Serial i/o exception"));
300  }
301  else if (ret == 0) {
302  // Timeout occured
303  return false;
304  }
305  else {
306  ssize_t n = ::read(m_fd, c, 1); // read one character at a time
307  if (n != 1)
308  return false;
309  }
310  return true;
311 }
312 
318 std::string vpSerial::readline(const std::string &eol)
319 {
320  char c;
321  size_t read_so_far = 0;
322  size_t eol_len = eol.length ();
323  std::string line;
324 
325  while(true) {
326  size_t bytes_read = this->read(&c, 1);
327  read_so_far += bytes_read;
328  if (bytes_read == 0) {
329  break; // Timeout occured on reading 1 byte
330  }
331  line.append(&c, 1);
332  if (std::string(line, line.size() - eol_len, eol_len) == eol) {
333  break; // EOL found
334  }
335  }
336  return line;
337 }
338 
343 void vpSerial::write(const std::string &s)
344 {
345  if (m_is_open == false) {
346  throw(vpException(vpException::fatalError, "Serial port not opened"));
347  }
348 
349  ssize_t r = ::write(m_fd, s.c_str(), s.size());
350  if (r != (ssize_t)(s.size())) {
351  throw(vpException(vpException::fatalError, "Serial port write error"));
352  }
353 }
354 
355 void vpSerial::configure()
356 {
357  if (m_fd == -1) {
358  throw(vpException(vpException::fatalError, "Serial port not opened"));
359  }
360 
361  struct termios options;
362 
363  if (tcgetattr(m_fd, &options) == -1) {
364  ::close(m_fd);
365  throw vpException(vpException::fatalError, "Cannot get serial configuration");
366  }
367 
368  // set up raw mode / no echo / binary
369  options.c_cflag |= (tcflag_t) (CLOCAL | CREAD);
370  options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
371  ISIG | IEXTEN); //|ECHOPRT
372 
373  options.c_oflag &= (tcflag_t) ~(OPOST);
374  options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
375 
376 #ifdef IUCLC
377  options.c_iflag &= (tcflag_t) ~IUCLC;
378 #endif
379 #ifdef PARMRK
380  options.c_iflag &= (tcflag_t) ~PARMRK;
381 #endif
382 
383  speed_t baudrate;
384  switch(m_baudrate) {
385 #ifdef B0
386  case 0: baudrate = B0; break;
387 #endif
388 #ifdef B50
389  case 50: baudrate = B50; break;
390 #endif
391 #ifdef B75
392  case 75: baudrate = B75; break;
393 #endif
394 #ifdef B110
395  case 110: baudrate = B110; break;
396 #endif
397 #ifdef B134
398  case 134: baudrate = B134; break;
399 #endif
400 #ifdef B150
401  case 150: baudrate = B150; break;
402 #endif
403 #ifdef B200
404  case 200: baudrate = B200; break;
405 #endif
406 #ifdef B300
407  case 300: baudrate = B300; break;
408 #endif
409 #ifdef B600
410  case 600: baudrate = B600; break;
411 #endif
412 #ifdef B1200
413  case 1200: baudrate = B1200; break;
414 #endif
415 #ifdef B1800
416  case 1800: baudrate = B1800; break;
417 #endif
418 #ifdef B2400
419  case 2400: baudrate = B2400; break;
420 #endif
421 #ifdef B4800
422  case 4800: baudrate = B4800; break;
423 #endif
424 #ifdef B9600
425  case 9600: baudrate = B9600; break;
426 #endif
427 #ifdef B14400
428  case 14400: baudrate = B14400; break;
429 #endif
430 #ifdef B19200
431  case 19200: baudrate = B19200; break;
432 #endif
433 #ifdef B38400
434  case 38400: baudrate = B38400; break;
435 #endif
436 #ifdef B57600
437  case 57600: baudrate = B57600; break;
438 #endif
439 #ifdef B115200
440  case 115200: baudrate = B115200; break;
441 #endif
442 #ifdef B230400
443  case 230400: baudrate = B230400; break;
444 #endif
445 #ifdef B460800
446  case 460800: baudrate = B460800; break;
447 #endif
448 #ifdef B500000
449  case 500000: baudrate = B500000; break;
450 #endif
451 #ifdef B576000
452  case 576000: baudrate = B576000; break;
453 #endif
454 #ifdef B921600
455  case 921600: baudrate = B921600; break;
456 #endif
457 #ifdef B1000000
458  case 1000000: baudrate = B1000000; break;
459 #endif
460 #ifdef B1152000
461  case 1152000: baudrate = B1152000; break;
462 #endif
463 #ifdef B1500000
464  case 1500000: baudrate = B1500000; break;
465 #endif
466 #ifdef B2000000
467  case 2000000: baudrate = B2000000; break;
468 #endif
469 #ifdef B2500000
470  case 2500000: baudrate = B2500000; break;
471 #endif
472 #ifdef B3000000
473  case 3000000: baudrate = B3000000; break;
474 #endif
475 #ifdef B3500000
476  case 3500000: baudrate = B3500000; break;
477 #endif
478 #ifdef B4000000
479  case 4000000: baudrate = B4000000; break;
480 #endif
481  default:
482  throw vpException(vpException::fatalError, "Cannot set serial baudrate to %ld", m_baudrate);
483  }
484 
485 #ifdef _BSD_SOURCE
486  ::cfsetspeed(&options, baudrate);
487 #else
488  ::cfsetispeed(&options, baudrate);
489  ::cfsetospeed(&options, baudrate);
490 #endif
491 
492  // setup char len
493  options.c_cflag &= (tcflag_t) ~CSIZE;
494  switch(m_bytesize) {
495  case eightbits: options.c_cflag |= CS8; break;
496  case sevenbits: options.c_cflag |= CS7; break;
497  case sixbits: options.c_cflag |= CS6; break;
498  case fivebits: options.c_cflag |= CS5; break;
499  }
500 
501  switch(m_stopbits) {
502  case stopbits_one: options.c_cflag &= (tcflag_t) ~(CSTOPB); break;
503  case stopbits_two: options.c_cflag |= (CSTOPB); break;
504  }
505 
506  // setup parity
507  options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
508  switch(m_parity) {
509  case parity_none:
510  options.c_cflag &= (tcflag_t) ~(PARENB | PARODD); break;
511  case parity_even:
512  options.c_cflag &= (tcflag_t) ~(PARODD);
513  options.c_cflag |= (PARENB); break;
514  case parity_odd:
515  options.c_cflag |= (PARENB | PARODD); break;
516  }
517 
518  // setup flow control
519  switch(m_flowcontrol) {
520  case flowcontrol_none:
521  m_xonxoff = false;
522  m_rtscts = false;
523  break;
525  m_xonxoff = true;
526  m_rtscts = false;
527  break;
529  m_xonxoff = false;
530  m_rtscts = true;
531  break;
532  }
533 
534  // xonxoff
535  if (m_xonxoff)
536  options.c_iflag |= (IXON | IXOFF);
537  else
538 #ifdef IXANY
539  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
540 #else
541  options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
542 #endif
543 
544  // rtscts
545 #ifdef CRTSCTS
546  if (m_rtscts)
547  options.c_cflag |= (CRTSCTS);
548  else
549  options.c_cflag &= (unsigned long) ~(CRTSCTS);
550 #elif defined CNEW_RTSCTS
551  if (m_rtscts)
552  options.c_cflag |= (CNEW_RTSCTS);
553  else
554  options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
555 #else
556 #error "OS doesn't support serial rtscts"
557 #endif
558 
559  options.c_cc[VMIN] = 0;
560  options.c_cc[VTIME] = 0;
561 
562  // activate settings
563  ::tcsetattr (m_fd, TCSANOW, &options);
564 }
565 
566 #elif !defined(VISP_BUILD_SHARED_LIBS)
567 // Work arround to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
568 void dummy_vpSerial(){};
569 #endif
Data is encoded with 6 bits.
Definition: vpSerial.h:78
vpSerial(const std::string &port="", unsigned long baudrate=9600, bytesize_t bytesize=eightbits, parity_t parity=parity_none, stopbits_t stopbits=stopbits_one, flowcontrol_t flowcontrol=flowcontrol_none)
Definition: vpSerial.cpp:100
virtual ~vpSerial()
Definition: vpSerial.cpp:114
flowcontrol_t
Definition: vpSerial.h:103
Data is encoded with 8 bits.
Definition: vpSerial.h:80
error that can be emited by ViSP classes.
Definition: vpException.h:71
No parity check.
Definition: vpSerial.h:87
void write(const std::string &s)
Definition: vpSerial.cpp:343
std::string readline(const std::string &eol)
Definition: vpSerial.cpp:318
int available()
Definition: vpSerial.cpp:189
void setBaudrate(const unsigned long baudrate)
Definition: vpSerial.cpp:123
Hardware flow control.
Definition: vpSerial.h:106
void setFlowcontrol(const flowcontrol_t &flowcontrol)
Definition: vpSerial.cpp:141
Data is encoded with 5 bits.
Definition: vpSerial.h:77
bool read(char *c, long timeout_s)
Definition: vpSerial.cpp:284
Check for odd parity.
Definition: vpSerial.h:88
No flow control.
Definition: vpSerial.h:104
void setPort(const std::string &port)
Definition: vpSerial.cpp:181
2 stop bits are used
Definition: vpSerial.h:97
void open()
Definition: vpSerial.cpp:249
stopbits_t
Definition: vpSerial.h:95
Check for even parity.
Definition: vpSerial.h:89
void close()
Definition: vpSerial.cpp:206
void setStopbits(const stopbits_t &stopbits)
Definition: vpSerial.cpp:159
Data is encoded with 7 bits.
Definition: vpSerial.h:79
1 stop bit is used
Definition: vpSerial.h:96
bytesize_t
Definition: vpSerial.h:76
void setParity(const parity_t &parity)
Definition: vpSerial.cpp:150
void setBytesize(const bytesize_t &bytesize)
Definition: vpSerial.cpp:132
Software flow control.
Definition: vpSerial.h:105