Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpSerial.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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*****************************************************************************/
35
36#include <visp3/core/vpConfig.h>
37
38#if !defined(_WIN32)
39
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <sys/ioctl.h>
46#include <sys/stat.h>
47#include <sys/types.h>
48#include <termios.h>
49#include <unistd.h>
50
51#include <visp3/core/vpException.h>
52#include <visp3/core/vpSerial.h>
53
54#ifndef TIOCINQ
55#ifdef FIONREAD
56#define TIOCINQ FIONREAD
57#else
58#define TIOCINQ 0x541B
59#endif
60#endif
61
97vpSerial::vpSerial(const std::string &port, unsigned long baudrate, bytesize_t bytesize, parity_t parity,
98 stopbits_t stopbits, flowcontrol_t flowcontrol)
99 : m_port(port), m_fd(-1), m_is_open(false), m_xonxoff(false), m_rtscts(false), m_baudrate(baudrate), m_parity(parity),
100 m_bytesize(bytesize), m_stopbits(stopbits), m_flowcontrol(flowcontrol)
101{
102 if (m_port.empty() == false)
103 open();
104}
105
110
115void vpSerial::setBaudrate(const unsigned long baudrate) { m_baudrate = baudrate; }
116
121void vpSerial::setBytesize(const bytesize_t &bytesize) { m_bytesize = bytesize; }
122
127void vpSerial::setFlowcontrol(const flowcontrol_t &flowcontrol) { m_flowcontrol = flowcontrol; }
128
133void vpSerial::setParity(const parity_t &parity) { m_parity = parity; }
134
139void vpSerial::setStopbits(const stopbits_t &stopbits) { m_stopbits = stopbits; }
140
158void vpSerial::setPort(const std::string &port) { m_port = port; }
159
164{
165 if (!m_is_open) {
166 return 0;
167 }
168 int count = 0;
169 if (-1 == ioctl(m_fd, TIOCINQ, &count)) {
170 throw(vpException(vpException::fatalError, "Cannot check is serial port data available"));
171 } else {
172 return count;
173 }
174}
175
181{
182 if (m_is_open == true) {
183 if (m_fd != -1) {
184 int ret;
185 ret = ::close(m_fd);
186 if (ret == 0) {
187 m_fd = -1;
188 } else {
189 throw(vpException(vpException::fatalError, "Cannot close serial port"));
190 }
191 }
192 m_is_open = false;
193 }
194}
195
224{
225 if (m_port.empty()) {
226 throw(vpException(vpException::fatalError, "Serial port empty"));
227 }
228 if (m_is_open == true) {
229 throw(vpException(vpException::fatalError, "Serial port already open"));
230 }
231
232 m_fd = ::open(m_port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
233
234 if (m_fd == -1) {
235 switch (errno) {
236 case EINTR:
237 // Try again because this is a recoverable error.
238 open();
239 return;
240 case ENFILE:
241 case EMFILE:
242 throw(vpException(vpException::fatalError, "Serial port has to many handles open"));
243 default:
244 throw(vpException(vpException::fatalError, "Serial port opening error"));
245 }
246 }
247
248 configure();
249 m_is_open = true;
250}
251
258bool vpSerial::read(char *c, long timeout_s)
259{
260 if (m_is_open == false) {
261 throw(vpException(vpException::fatalError, "Serial port not opened"));
262 }
263
264 fd_set readfds; /* list of fds for select to listen to */
265 struct timeval timeout = {timeout_s, 0}; // seconde, micro-sec
266
267 FD_ZERO(&readfds);
268 FD_SET(static_cast<unsigned int>(m_fd), &readfds);
269
270 int ret = select(FD_SETSIZE, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timeout);
271
272 if (ret < 0) {
273 throw(vpException(vpException::fatalError, "Serial i/o exception"));
274 } else if (ret == 0) {
275 // Timeout occurred
276 return false;
277 } else {
278 ssize_t n = ::read(m_fd, c, 1); // read one character at a time
279 if (n != 1)
280 return false;
281 }
282 return true;
283}
284
290std::string vpSerial::readline(const std::string &eol)
291{
292 char c;
293 size_t eol_len = eol.length();
294 std::string line;
295
296 while (true) {
297 size_t bytes_read = this->read(&c, 1);
298 if (bytes_read == 0) {
299 break; // Timeout occurred on reading 1 byte
300 }
301 line.append(&c, 1);
302 if (std::string(line, line.size() - eol_len, eol_len) == eol) {
303 break; // EOL found
304 }
305 }
306 return line;
307}
308
313void vpSerial::write(const std::string &s)
314{
315 if (m_is_open == false) {
316 throw(vpException(vpException::fatalError, "Serial port not opened"));
317 }
318
319 ssize_t r = ::write(m_fd, s.c_str(), s.size());
320 if (r != (ssize_t)(s.size())) {
321 throw(vpException(vpException::fatalError, "Serial port write error"));
322 }
323}
324
325void vpSerial::configure()
326{
327 if (m_fd == -1) {
328 throw(vpException(vpException::fatalError, "Serial port not opened"));
329 }
330
331 struct termios options;
332
333 if (tcgetattr(m_fd, &options) == -1) {
334 ::close(m_fd);
335 throw vpException(vpException::fatalError, "Cannot get serial configuration");
336 }
337
338 // set up raw mode / no echo / binary
339 options.c_cflag |= (tcflag_t)(CLOCAL | CREAD);
340 options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN); //|ECHOPRT
341
342 options.c_oflag &= (tcflag_t) ~(OPOST);
343 options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
344
345#ifdef IUCLC
346 options.c_iflag &= (tcflag_t)~IUCLC;
347#endif
348#ifdef PARMRK
349 options.c_iflag &= (tcflag_t)~PARMRK;
350#endif
351
352 speed_t baudrate;
353 switch (m_baudrate) {
354#ifdef B0
355 case 0:
356 baudrate = B0;
357 break;
358#endif
359#ifdef B50
360 case 50:
361 baudrate = B50;
362 break;
363#endif
364#ifdef B75
365 case 75:
366 baudrate = B75;
367 break;
368#endif
369#ifdef B110
370 case 110:
371 baudrate = B110;
372 break;
373#endif
374#ifdef B134
375 case 134:
376 baudrate = B134;
377 break;
378#endif
379#ifdef B150
380 case 150:
381 baudrate = B150;
382 break;
383#endif
384#ifdef B200
385 case 200:
386 baudrate = B200;
387 break;
388#endif
389#ifdef B300
390 case 300:
391 baudrate = B300;
392 break;
393#endif
394#ifdef B600
395 case 600:
396 baudrate = B600;
397 break;
398#endif
399#ifdef B1200
400 case 1200:
401 baudrate = B1200;
402 break;
403#endif
404#ifdef B1800
405 case 1800:
406 baudrate = B1800;
407 break;
408#endif
409#ifdef B2400
410 case 2400:
411 baudrate = B2400;
412 break;
413#endif
414#ifdef B4800
415 case 4800:
416 baudrate = B4800;
417 break;
418#endif
419#ifdef B9600
420 case 9600:
421 baudrate = B9600;
422 break;
423#endif
424#ifdef B14400
425 case 14400:
426 baudrate = B14400;
427 break;
428#endif
429#ifdef B19200
430 case 19200:
431 baudrate = B19200;
432 break;
433#endif
434#ifdef B38400
435 case 38400:
436 baudrate = B38400;
437 break;
438#endif
439#ifdef B57600
440 case 57600:
441 baudrate = B57600;
442 break;
443#endif
444#ifdef B115200
445 case 115200:
446 baudrate = B115200;
447 break;
448#endif
449#ifdef B230400
450 case 230400:
451 baudrate = B230400;
452 break;
453#endif
454#ifdef B460800
455 case 460800:
456 baudrate = B460800;
457 break;
458#endif
459#ifdef B500000
460 case 500000:
461 baudrate = B500000;
462 break;
463#endif
464#ifdef B576000
465 case 576000:
466 baudrate = B576000;
467 break;
468#endif
469#ifdef B921600
470 case 921600:
471 baudrate = B921600;
472 break;
473#endif
474#ifdef B1000000
475 case 1000000:
476 baudrate = B1000000;
477 break;
478#endif
479#ifdef B1152000
480 case 1152000:
481 baudrate = B1152000;
482 break;
483#endif
484#ifdef B1500000
485 case 1500000:
486 baudrate = B1500000;
487 break;
488#endif
489#ifdef B2000000
490 case 2000000:
491 baudrate = B2000000;
492 break;
493#endif
494#ifdef B2500000
495 case 2500000:
496 baudrate = B2500000;
497 break;
498#endif
499#ifdef B3000000
500 case 3000000:
501 baudrate = B3000000;
502 break;
503#endif
504#ifdef B3500000
505 case 3500000:
506 baudrate = B3500000;
507 break;
508#endif
509#ifdef B4000000
510 case 4000000:
511 baudrate = B4000000;
512 break;
513#endif
514 default:
515 throw vpException(vpException::fatalError, "Cannot set serial baudrate to %ld", m_baudrate);
516 }
517
518#ifdef _BSD_SOURCE
519 ::cfsetspeed(&options, baudrate);
520#else
521 ::cfsetispeed(&options, baudrate);
522 ::cfsetospeed(&options, baudrate);
523#endif
524
525 // setup char len
526 options.c_cflag &= (tcflag_t)~CSIZE;
527 switch (m_bytesize) {
528 case eightbits:
529 options.c_cflag |= CS8;
530 break;
531 case sevenbits:
532 options.c_cflag |= CS7;
533 break;
534 case sixbits:
535 options.c_cflag |= CS6;
536 break;
537 case fivebits:
538 options.c_cflag |= CS5;
539 break;
540 }
541
542 switch (m_stopbits) {
543 case stopbits_one:
544 options.c_cflag &= (tcflag_t) ~(CSTOPB);
545 break;
546 case stopbits_two:
547 options.c_cflag |= (CSTOPB);
548 break;
549 }
550
551 // setup parity
552 options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
553 switch (m_parity) {
554 case parity_none:
555 options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
556 break;
557 case parity_even:
558 options.c_cflag &= (tcflag_t) ~(PARODD);
559 options.c_cflag |= (PARENB);
560 break;
561 case parity_odd:
562 options.c_cflag |= (PARENB | PARODD);
563 break;
564 }
565
566 // setup flow control
567 switch (m_flowcontrol) {
568 case flowcontrol_none:
569 m_xonxoff = false;
570 m_rtscts = false;
571 break;
573 m_xonxoff = true;
574 m_rtscts = false;
575 break;
577 m_xonxoff = false;
578 m_rtscts = true;
579 break;
580 }
581
582 // xonxoff
583 if (m_xonxoff)
584 options.c_iflag |= (IXON | IXOFF);
585 else
586#ifdef IXANY
587 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
588#else
589 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
590#endif
591
592 // rtscts
593#ifdef CRTSCTS
594 if (m_rtscts)
595 options.c_cflag |= (CRTSCTS);
596 else
597 options.c_cflag &= (unsigned long)~(CRTSCTS);
598#elif defined CNEW_RTSCTS
599 if (m_rtscts)
600 options.c_cflag |= (CNEW_RTSCTS);
601 else
602 options.c_cflag &= (unsigned long)~(CNEW_RTSCTS);
603#else
604#error "OS doesn't support serial rtscts"
605#endif
606
607 options.c_cc[VMIN] = 0;
608 options.c_cc[VTIME] = 0;
609
610 // activate settings
611 ::tcsetattr(m_fd, TCSANOW, &options);
612}
613
614#elif !defined(VISP_BUILD_SHARED_LIBS)
615// Work around to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
616void dummy_vpSerial(){};
617#endif
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ fatalError
Fatal error.
Definition vpException.h:84
std::string readline(const std::string &eol)
Definition vpSerial.cpp:290
flowcontrol_t
Definition vpSerial.h:98
@ flowcontrol_software
Software flow control.
Definition vpSerial.h:100
@ flowcontrol_none
No flow control.
Definition vpSerial.h:99
@ flowcontrol_hardware
Hardware flow control.
Definition vpSerial.h:101
void open()
Definition vpSerial.cpp:223
void setParity(const parity_t &parity)
Definition vpSerial.cpp:133
int available()
Definition vpSerial.cpp:163
void setStopbits(const stopbits_t &stopbits)
Definition vpSerial.cpp:139
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:97
@ parity_odd
Check for odd parity.
Definition vpSerial.h:83
@ parity_none
No parity check.
Definition vpSerial.h:82
@ parity_even
Check for even parity.
Definition vpSerial.h:84
void close()
Definition vpSerial.cpp:180
@ stopbits_two
2 stop bits are used
Definition vpSerial.h:92
@ stopbits_one
1 stop bit is used
Definition vpSerial.h:91
void setFlowcontrol(const flowcontrol_t &flowcontrol)
Definition vpSerial.cpp:127
bool read(char *c, long timeout_s)
Definition vpSerial.cpp:258
void setBytesize(const bytesize_t &bytesize)
Definition vpSerial.cpp:121
void write(const std::string &s)
Definition vpSerial.cpp:313
virtual ~vpSerial()
Definition vpSerial.cpp:109
void setPort(const std::string &port)
Definition vpSerial.cpp:158
@ eightbits
Data is encoded with 8 bits.
Definition vpSerial.h:75
@ fivebits
Data is encoded with 5 bits.
Definition vpSerial.h:72
@ sevenbits
Data is encoded with 7 bits.
Definition vpSerial.h:74
@ sixbits
Data is encoded with 6 bits.
Definition vpSerial.h:73
void setBaudrate(const unsigned long baudrate)
Definition vpSerial.cpp:115