17 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE) 30 #include <sys/ioctl.h> 33 #ifdef HAVE_LINUX_SERIAL_H 34 #include <linux/serial.h> 39 #endif // Linux | Apple 41 #ifdef MRPT_OS_WINDOWS 51 CSerialPort::CSerialPort(
const string &portName,
bool openNow ) :
52 m_serialName(portName),
54 m_interBytesTimeout_ms(0),
55 #ifdef MRPT_OS_WINDOWS
68 m_interBytesTimeout_ms(0),
69 #ifdef MRPT_OS_WINDOWS
90 #ifdef MRPT_OS_WINDOWS 104 if (INVALID_HANDLE_VALUE == (
107 GENERIC_READ | GENERIC_WRITE,
119 SetupComm(
hCOM, 4096, 4096);
133 fcntl(
hCOM, F_SETFL, 0 );
138 termios port_settings;
139 bzero( &port_settings,
sizeof( port_settings ) ) ;
145 port_settings.c_cflag |= CREAD | CLOCAL ;
155 port_settings.c_cc[ VMIN ] = 0 ;
156 port_settings.c_cc[ VTIME ] = 0 ;
161 if ( tcflush(
hCOM,TCIFLUSH ) < 0 )
167 if ( tcsetattr(
hCOM,TCSANOW,&port_settings ) < 0 )
172 fcntl(
hCOM, F_SETFL, FNDELAY);
185 #ifdef MRPT_OS_WINDOWS 200 bool enableFlowControl )
203 #ifdef MRPT_OS_WINDOWS 206 dcb_conf.DCBlength =
sizeof(DCB);
219 case 300: BR = CBR_300;
break;
220 case 600: BR = CBR_600;
break;
221 case 1200: BR = CBR_1200;
break;
222 case 2400: BR = CBR_2400;
break;
223 case 4800: BR = CBR_4800;
break;
224 case 9600: BR = CBR_9600;
break;
225 case 19200: BR = CBR_19200;
break;
226 case 38400: BR = CBR_38400;
break;
227 case 57600: BR = CBR_57600;
break;
228 case 115200: BR = CBR_115200;
break;
235 dcb_conf.BaudRate = BR;
238 dcb_conf.ByteSize = (BYTE)bits;
239 dcb_conf.Parity = (BYTE)parity;
245 dcb_conf.StopBits = ONESTOPBIT;
248 dcb_conf.StopBits = TWOSTOPBITS;
255 dcb_conf.fBinary =
true;
256 dcb_conf.fParity = parity != 0;
258 dcb_conf.fRtsControl = enableFlowControl ? RTS_CONTROL_HANDSHAKE : RTS_CONTROL_DISABLE;
259 dcb_conf.fOutxCtsFlow = enableFlowControl;
262 if (!SetCommState(
hCOM, &dcb_conf))
266 if (!GetCommState(
hCOM, &dcb_conf))
268 if (((
int)dcb_conf.BaudRate) != baudRate)
283 bool special_rate =
false;
286 case 50: BR = B50;
break;
287 case 75: BR = B75;
break;
288 case 110: BR = B110;
break;
289 case 134: BR = B134;
break;
290 case 200: BR = B200;
break;
291 case 300: BR = B300;
break;
292 case 600: BR = B600;
break;
293 case 1200: BR = B1200;
break;
294 case 2400: BR = B2400;
break;
295 case 4800: BR = B4800;
break;
296 case 9600: BR = B9600;
break;
297 case 19200: BR = B19200;
break;
298 case 38400: BR = B38400;
break;
299 case 57600: BR = B57600;
break;
300 case 115200: BR = B115200;
break;
301 case 230400: BR = B230400;
break;
303 case 460800: BR = B460800;
break;
306 case 500000: BR = B500000;
break;
309 case 576000: BR = B576000;
break;
310 case 921600: BR = B921600;
break;
311 case 1000000: BR = B1000000;
break;
312 case 1152000: BR = B1152000;
break;
313 case 1500000: BR = B1500000;
break;
314 case 2000000: BR = B2000000;
break;
315 case 2500000: BR = B2500000;
break;
316 case 3000000: BR = B3000000;
break;
317 case 3500000: BR = B3500000;
break;
318 case 4000000: BR = B4000000;
break;
321 #ifdef HAVE_LINUX_SERIAL_H 331 #ifdef HAVE_LINUX_SERIAL_H 332 struct serial_struct serial;
333 if (ioctl(
hCOM, TIOCGSERIAL, &serial) < 0)
336 serial.custom_divisor = serial.baud_base / baudRate;
337 if (!serial.custom_divisor) serial.custom_divisor = 1;
338 const int actual_rate = serial.baud_base / serial.custom_divisor;
340 serial.flags &= ~ASYNC_SPD_MASK;
341 serial.flags |= ASYNC_SPD_CUST;
343 if (ioctl(
hCOM, TIOCSSERIAL, &serial) < 0)
348 if (actual_rate!=baudRate)
349 cout <<
"[CSerialPort::setConfig] Setting custom baud rate to " << actual_rate <<
", the closer I can make to " << baudRate << endl;
351 THROW_EXCEPTION(
"Custom serial port baud rates require linux/serial.h");
369 termios port_settings;
370 if ( tcgetattr(
hCOM, & port_settings ) < 0 )
373 if ( ( cfsetispeed( &port_settings,BR ) < 0 ) ||
374 ( cfsetospeed( &port_settings,BR) < 0 ) )
380 port_settings.c_cflag &= ~CSIZE ;
384 port_settings.c_cflag |= CS5;
387 port_settings.c_cflag |= CS6;
390 port_settings.c_cflag |= CS7;
393 port_settings.c_cflag |= CS8;
404 port_settings.c_cflag |= PARENB ;
405 port_settings.c_cflag &= ~PARODD ;
406 port_settings.c_iflag |= INPCK ;
409 port_settings.c_cflag |= ( PARENB | PARODD );
410 port_settings.c_iflag |= INPCK;
413 port_settings.c_cflag &= ~(PARENB);
414 port_settings.c_iflag |= IGNPAR;
425 port_settings.c_cflag &= ~(CSTOPB) ;
428 port_settings.c_cflag |= CSTOPB ;
438 if (enableFlowControl)
441 port_settings.c_cflag |= CRTSCTS ;
446 port_settings.c_cflag &= ~(CRTSCTS) ;
451 if ( tcsetattr(
hCOM,TCSANOW,&port_settings ) < 0 )
455 termios port_settings_verif;
456 if ( tcgetattr(
hCOM, & port_settings_verif) < 0 )
462 if (port_settings_verif.c_ispeed != port_settings.c_ispeed)
464 if (port_settings_verif.c_ospeed != port_settings.c_ospeed)
468 if (port_settings_verif.c_cflag != port_settings.c_cflag)
478 int ReadIntervalTimeout,
479 int ReadTotalTimeoutMultiplier,
480 int ReadTotalTimeoutConstant,
481 int WriteTotalTimeoutMultiplier,
482 int WriteTotalTimeoutConstant )
485 #ifdef MRPT_OS_WINDOWS 486 COMMTIMEOUTS timeouts;
493 timeouts.ReadIntervalTimeout = ReadIntervalTimeout;
494 timeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier;
495 timeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant;
496 timeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier;
497 timeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
499 if (!SetCommTimeouts(
hCOM, &timeouts))
513 termios port_settings;
514 if (tcgetattr(
hCOM, &port_settings) < 0)
519 port_settings.c_cc[VMIN] = 0;
520 port_settings.c_cc[VTIME] = max(1, ReadTotalTimeoutConstant / 100);
524 if (tcsetattr(
hCOM, TCSANOW, &port_settings) < 0)
536 #ifdef MRPT_OS_WINDOWS 559 #ifdef MRPT_OS_WINDOWS 580 if (!Count)
return 0;
586 size_t alreadyRead = 0;
589 while ( alreadyRead<Count && leftTime>=0 )
594 if ( ioctl(
hCOM, FIONREAD, &waiting_bytes) < 0)
609 int nToRead =
min( (
size_t)waiting_bytes, Count-alreadyRead );
611 if ( ( nRead=::read(
hCOM, ((
char*)Buffer)+alreadyRead, nToRead ) ) <0 )
613 cerr <<
"[CSerialPort] Error reading from port..." << endl;
623 if (alreadyRead<Count)
645 const int total_timeout_ms,
647 const char *eol_chars)
657 if (out_timeout) *out_timeout =
false;
662 while (total_timeout_ms<0 || (
m_timer.
Tac()*1e3 < total_timeout_ms))
664 #ifdef MRPT_OS_WINDOWS 679 if (!strchr(eol_chars, buf[0]))
680 receivedStr.push_back(buf[0]);
691 int waiting_bytes = 0;
692 if (ioctl(
hCOM, FIONREAD, &waiting_bytes) < 0)
707 if ((nRead = ::read(
hCOM, buf, 1)) <0)
709 cerr <<
"[CSerialPort] Error reading from port..." << endl;
713 if (!strchr(eol_chars, buf[0]))
714 receivedStr.push_back(buf[0]);
732 if (out_timeout) *out_timeout =
true;
743 #ifdef MRPT_OS_WINDOWS 744 DWORD actuallyWritten;
752 return actuallyWritten;
759 int num_of_bytes_written = -1 ;
760 size_t total_bytes_written = 0;
763 gettimeofday(&
start, NULL);
764 num_of_bytes_written = write(
hCOM,reinterpret_cast<const char*>(Buffer)+total_bytes_written, Count-total_bytes_written );
766 if (num_of_bytes_written>0)
767 total_bytes_written+=num_of_bytes_written;
769 if (num_of_bytes_written<(
int)Count)
778 gettimeofday(&
end, NULL);
779 usecs= (
end.tv_sec -
start.tv_sec)*1000000 +
781 }
while (usecs < 60);
785 while ( ( total_bytes_written<Count) &&
786 ( !errno || EAGAIN == errno ) ) ;
788 if ( num_of_bytes_written < 0 )
796 return total_bytes_written;
809 #ifdef MRPT_OS_WINDOWS 810 if (!PurgeComm(
hCOM, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR))
814 if ( tcflush(
hCOM,TCIFLUSH ) < 0 )
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool isOpen() const
Returns if port has been correctly open.
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
Changes the timeouts of the port, in milliseconds.
#define THROW_EXCEPTION(msg)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Contains classes for various device interfaces.
int m_interBytesTimeout_ms
size_t Write(const void *Buffer, size_t Count)
Implements the virtual method responsible for writing to the stream.
void Tic()
Starts the stopwatch.
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time...
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
Changes the configuration of the port.
mrpt::utils::CTicTac m_timer
Used only in ReadString.
GLsizei const GLchar ** string
void close()
Close the port.
CSerialPort()
Default constructor: it does not open any port - later you must call "setSerialPortName" and then "op...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
int hCOM
The file handle (-1: Not open)
void purgeBuffers()
Purge tx and rx buffers.
std::string ReadString(const int total_timeout_ms=-1, bool *out_timeout=NULL, const char *eol_chars="\")
Reads one text line from the serial port in POSIX "canonical mode".
void open()
Open the port.
double Tac()
Stops the stopwatch.
std::string m_serialName
The complete name of the serial port device (i.e.
virtual ~CSerialPort()
Destructor.
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer, this method will not raise an exception on zero bytes read, as long as there is not any fatal error in the communications.