Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpSerial.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Serial communication.
32 */
33
34#include <visp3/core/vpConfig.h>
35
36#if !defined(_WIN32)
37
38#include <errno.h>
39#include <fcntl.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/ioctl.h>
44#include <sys/stat.h>
45#include <sys/types.h>
46#include <termios.h>
47#include <unistd.h>
48
49#include <visp3/core/vpException.h>
50#include <visp3/core/vpSerial.h>
51
52#ifndef TIOCINQ
53#ifdef FIONREAD
54#define TIOCINQ FIONREAD
55#else
56#define TIOCINQ 0x541B
57#endif
58#endif
59
104 vpSerial::vpSerial(const std::string &port, unsigned long baudrate, bytesize_t bytesize, parity_t parity,
105 stopbits_t stopbits, flowcontrol_t flowcontrol)
106 : m_port(port), m_fd(-1), m_is_open(false), m_xonxoff(false), m_rtscts(false), m_baudrate(baudrate), m_parity(parity),
107 m_bytesize(bytesize), m_stopbits(stopbits), m_flowcontrol(flowcontrol)
108{
109 if (m_port.empty() == false)
110 open();
111}
112
117
122void vpSerial::setBaudrate(const unsigned long baudrate) { m_baudrate = baudrate; }
123
128void vpSerial::setBytesize(const bytesize_t &bytesize) { m_bytesize = bytesize; }
129
134void vpSerial::setFlowcontrol(const flowcontrol_t &flowcontrol) { m_flowcontrol = flowcontrol; }
135
140void vpSerial::setParity(const parity_t &parity) { m_parity = parity; }
141
146void vpSerial::setStopbits(const stopbits_t &stopbits) { m_stopbits = stopbits; }
147
169void vpSerial::setPort(const std::string &port) { m_port = port; }
170
175{
176 if (!m_is_open) {
177 return 0;
178 }
179 int count = 0;
180 if (-1 == ioctl(m_fd, TIOCINQ, &count)) {
181 throw(vpException(vpException::fatalError, "Cannot check is serial port data available"));
182 }
183 else {
184 return count;
185 }
186}
187
193{
194 if (m_is_open == true) {
195 if (m_fd != -1) {
196 int ret;
197 ret = ::close(m_fd);
198 if (ret == 0) {
199 m_fd = -1;
200 }
201 else {
202 throw(vpException(vpException::fatalError, "Cannot close serial port"));
203 }
204 }
205 m_is_open = false;
206 }
207}
208
241{
242 if (m_port.empty()) {
243 throw(vpException(vpException::fatalError, "Serial port empty"));
244 }
245 if (m_is_open == true) {
246 throw(vpException(vpException::fatalError, "Serial port already open"));
247 }
248
249 m_fd = ::open(m_port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
250
251 if (m_fd == -1) {
252 switch (errno) {
253 case EINTR:
254 // Try again because this is a recoverable error.
255 open();
256 return;
257 case ENFILE:
258 case EMFILE:
259 throw(vpException(vpException::fatalError, "Serial port has to many handles open"));
260 default:
261 throw(vpException(vpException::fatalError, "Serial port opening error"));
262 }
263 }
264
265 configure();
266 m_is_open = true;
267}
268
275bool vpSerial::read(char *c, long timeout_s)
276{
277 if (m_is_open == false) {
278 throw(vpException(vpException::fatalError, "Serial port not opened"));
279 }
280
281 fd_set readfds; /* list of fds for select to listen to */
282 struct timeval timeout = { timeout_s, 0 }; // seconde, micro-sec
283
284 FD_ZERO(&readfds);
285 FD_SET(static_cast<unsigned int>(m_fd), &readfds);
286
287 int ret = select(FD_SETSIZE, &readfds, (fd_set *)nullptr, (fd_set *)nullptr, &timeout);
288
289 if (ret < 0) {
290 throw(vpException(vpException::fatalError, "Serial i/o exception"));
291 }
292 else if (ret == 0) {
293 // Timeout occurred
294 return false;
295 }
296 else {
297 ssize_t n = ::read(m_fd, c, 1); // read one character at a time
298 if (n != 1)
299 return false;
300 }
301 return true;
302}
303
309std::string vpSerial::readline(const std::string &eol)
310{
311 char c;
312 size_t eol_len = eol.length();
313 std::string line;
314
315 while (true) {
316 size_t bytes_read = this->read(&c, 1);
317 if (bytes_read == 0) {
318 break; // Timeout occurred on reading 1 byte
319 }
320 line.append(&c, 1);
321 if (std::string(line, line.size() - eol_len, eol_len) == eol) {
322 break; // EOL found
323 }
324 }
325 return line;
326}
327
332void vpSerial::write(const std::string &s)
333{
334 if (m_is_open == false) {
335 throw(vpException(vpException::fatalError, "Serial port not opened"));
336 }
337
338 ssize_t r = ::write(m_fd, s.c_str(), s.size());
339 if (r != (ssize_t)(s.size())) {
340 throw(vpException(vpException::fatalError, "Serial port write error"));
341 }
342}
343
344void vpSerial::configure()
345{
346 if (m_fd == -1) {
347 throw(vpException(vpException::fatalError, "Serial port not opened"));
348 }
349
350 struct termios options;
351
352 if (tcgetattr(m_fd, &options) == -1) {
353 ::close(m_fd);
354 throw vpException(vpException::fatalError, "Cannot get serial configuration");
355 }
356
357 // set up raw mode / no echo / binary
358 options.c_cflag |= (tcflag_t)(CLOCAL | CREAD);
359 options.c_lflag &= (tcflag_t)~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN); //|ECHOPRT
360
361 options.c_oflag &= (tcflag_t)~(OPOST);
362 options.c_iflag &= (tcflag_t)~(INLCR | IGNCR | ICRNL | IGNBRK);
363
364#ifdef IUCLC
365 options.c_iflag &= (tcflag_t)~IUCLC;
366#endif
367#ifdef PARMRK
368 options.c_iflag &= (tcflag_t)~PARMRK;
369#endif
370
371 speed_t baudrate;
372 switch (m_baudrate) {
373#ifdef B0
374 case 0:
375 baudrate = B0;
376 break;
377#endif
378#ifdef B50
379 case 50:
380 baudrate = B50;
381 break;
382#endif
383#ifdef B75
384 case 75:
385 baudrate = B75;
386 break;
387#endif
388#ifdef B110
389 case 110:
390 baudrate = B110;
391 break;
392#endif
393#ifdef B134
394 case 134:
395 baudrate = B134;
396 break;
397#endif
398#ifdef B150
399 case 150:
400 baudrate = B150;
401 break;
402#endif
403#ifdef B200
404 case 200:
405 baudrate = B200;
406 break;
407#endif
408#ifdef B300
409 case 300:
410 baudrate = B300;
411 break;
412#endif
413#ifdef B600
414 case 600:
415 baudrate = B600;
416 break;
417#endif
418#ifdef B1200
419 case 1200:
420 baudrate = B1200;
421 break;
422#endif
423#ifdef B1800
424 case 1800:
425 baudrate = B1800;
426 break;
427#endif
428#ifdef B2400
429 case 2400:
430 baudrate = B2400;
431 break;
432#endif
433#ifdef B4800
434 case 4800:
435 baudrate = B4800;
436 break;
437#endif
438#ifdef B9600
439 case 9600:
440 baudrate = B9600;
441 break;
442#endif
443#ifdef B14400
444 case 14400:
445 baudrate = B14400;
446 break;
447#endif
448#ifdef B19200
449 case 19200:
450 baudrate = B19200;
451 break;
452#endif
453#ifdef B38400
454 case 38400:
455 baudrate = B38400;
456 break;
457#endif
458#ifdef B57600
459 case 57600:
460 baudrate = B57600;
461 break;
462#endif
463#ifdef B115200
464 case 115200:
465 baudrate = B115200;
466 break;
467#endif
468#ifdef B230400
469 case 230400:
470 baudrate = B230400;
471 break;
472#endif
473#ifdef B460800
474 case 460800:
475 baudrate = B460800;
476 break;
477#endif
478#ifdef B500000
479 case 500000:
480 baudrate = B500000;
481 break;
482#endif
483#ifdef B576000
484 case 576000:
485 baudrate = B576000;
486 break;
487#endif
488#ifdef B921600
489 case 921600:
490 baudrate = B921600;
491 break;
492#endif
493#ifdef B1000000
494 case 1000000:
495 baudrate = B1000000;
496 break;
497#endif
498#ifdef B1152000
499 case 1152000:
500 baudrate = B1152000;
501 break;
502#endif
503#ifdef B1500000
504 case 1500000:
505 baudrate = B1500000;
506 break;
507#endif
508#ifdef B2000000
509 case 2000000:
510 baudrate = B2000000;
511 break;
512#endif
513#ifdef B2500000
514 case 2500000:
515 baudrate = B2500000;
516 break;
517#endif
518#ifdef B3000000
519 case 3000000:
520 baudrate = B3000000;
521 break;
522#endif
523#ifdef B3500000
524 case 3500000:
525 baudrate = B3500000;
526 break;
527#endif
528#ifdef B4000000
529 case 4000000:
530 baudrate = B4000000;
531 break;
532#endif
533 default:
534 throw vpException(vpException::fatalError, "Cannot set serial baudrate to %ld", m_baudrate);
535 }
536
537#ifdef _BSD_SOURCE
538 ::cfsetspeed(&options, baudrate);
539#else
540 ::cfsetispeed(&options, baudrate);
541 ::cfsetospeed(&options, baudrate);
542#endif
543
544 // setup char len
545 options.c_cflag &= (tcflag_t)~CSIZE;
546 switch (m_bytesize) {
547 case eightbits:
548 options.c_cflag |= CS8;
549 break;
550 case sevenbits:
551 options.c_cflag |= CS7;
552 break;
553 case sixbits:
554 options.c_cflag |= CS6;
555 break;
556 case fivebits:
557 options.c_cflag |= CS5;
558 break;
559 }
560
561 switch (m_stopbits) {
562 case stopbits_one:
563 options.c_cflag &= (tcflag_t)~(CSTOPB);
564 break;
565 case stopbits_two:
566 options.c_cflag |= (CSTOPB);
567 break;
568 }
569
570 // setup parity
571 options.c_iflag &= (tcflag_t)~(INPCK | ISTRIP);
572 switch (m_parity) {
573 case parity_none:
574 options.c_cflag &= (tcflag_t)~(PARENB | PARODD);
575 break;
576 case parity_even:
577 options.c_cflag &= (tcflag_t)~(PARODD);
578 options.c_cflag |= (PARENB);
579 break;
580 case parity_odd:
581 options.c_cflag |= (PARENB | PARODD);
582 break;
583 }
584
585 // setup flow control
586 switch (m_flowcontrol) {
587 case flowcontrol_none:
588 m_xonxoff = false;
589 m_rtscts = false;
590 break;
592 m_xonxoff = true;
593 m_rtscts = false;
594 break;
596 m_xonxoff = false;
597 m_rtscts = true;
598 break;
599 }
600
601 // xonxoff
602 if (m_xonxoff)
603 options.c_iflag |= (IXON | IXOFF);
604 else
605#ifdef IXANY
606 options.c_iflag &= (tcflag_t)~(IXON | IXOFF | IXANY);
607#else
608 options.c_iflag &= (tcflag_t)~(IXON | IXOFF);
609#endif
610
611 // rtscts
612#ifdef CRTSCTS
613 if (m_rtscts)
614 options.c_cflag |= (CRTSCTS);
615 else
616 options.c_cflag &= (unsigned long)~(CRTSCTS);
617#elif defined CNEW_RTSCTS
618 if (m_rtscts)
619 options.c_cflag |= (CNEW_RTSCTS);
620 else
621 options.c_cflag &= (unsigned long)~(CNEW_RTSCTS);
622#else
623#error "OS doesn't support serial rtscts"
624#endif
625
626 options.c_cc[VMIN] = 0;
627 options.c_cc[VTIME] = 0;
628
629 // activate settings
630 ::tcsetattr(m_fd, TCSANOW, &options);
631}
632END_VISP_NAMESPACE
633#elif !defined(VISP_BUILD_SHARED_LIBS)
634// Work around to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
635void dummy_vpSerial() { }
636#endif
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ fatalError
Fatal error.
Definition vpException.h:72
std::string readline(const std::string &eol)
Definition vpSerial.cpp:309
@ flowcontrol_software
Software flow control.
Definition vpSerial.h:109
@ flowcontrol_none
No flow control.
Definition vpSerial.h:108
@ flowcontrol_hardware
Hardware flow control.
Definition vpSerial.h:110
void open()
Definition vpSerial.cpp:240
void setParity(const parity_t &parity)
Definition vpSerial.cpp:140
int available()
Definition vpSerial.cpp:174
void setStopbits(const stopbits_t &stopbits)
Definition vpSerial.cpp:146
@ parity_odd
Check for odd parity.
Definition vpSerial.h:90
@ parity_none
No parity check.
Definition vpSerial.h:89
@ parity_even
Check for even parity.
Definition vpSerial.h:91
void close()
Definition vpSerial.cpp:192
@ stopbits_two
2 stop bits are used
Definition vpSerial.h:100
@ stopbits_one
1 stop bit is used
Definition vpSerial.h:99
void setFlowcontrol(const flowcontrol_t &flowcontrol)
Definition vpSerial.cpp:134
bool read(char *c, long timeout_s)
Definition vpSerial.cpp:275
void setBytesize(const bytesize_t &bytesize)
Definition vpSerial.cpp:128
void write(const std::string &s)
Definition vpSerial.cpp:332
virtual ~vpSerial()
Definition vpSerial.cpp:116
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:104
void setPort(const std::string &port)
Definition vpSerial.cpp:169
@ eightbits
Data is encoded with 8 bits.
Definition vpSerial.h:81
@ fivebits
Data is encoded with 5 bits.
Definition vpSerial.h:78
@ sevenbits
Data is encoded with 7 bits.
Definition vpSerial.h:80
@ sixbits
Data is encoded with 6 bits.
Definition vpSerial.h:79
void setBaudrate(const unsigned long baudrate)
Definition vpSerial.cpp:122