17#include <itksys/SystemTools.hxx>
28#define INVALID_HANDLE_VALUE -1
35 m_DeviceName(
""), m_PortNumber(COM1), m_BaudRate(BaudRate9600),
36 m_DataBits(DataBits8), m_Parity(None), m_StopBits(StopBits1),
37 m_HardwareHandshake(HardwareHandshakeOff),
38 m_ReceiveTimeout(500), m_SendTimeout(500), m_Connected(false)
64 if (m_DeviceName.empty())
65 ss <<
"\\\\.\\COM" <<
static_cast<unsigned int>(m_PortNumber);
67 ss <<
"\\\\.\\" << m_DeviceName;
69 m_ComPortHandle = CreateFileA(ss.str().c_str(), GENERIC_READ | GENERIC_WRITE,
78 GetCommState(m_ComPortHandle, &m_PreviousDeviceControlBlock);
79 GetCommTimeouts(m_ComPortHandle, &m_PreviousTimeout);
80 GetCommMask(m_ComPortHandle, &m_PreviousMask);
82 if (this->ApplyConfiguration() !=
OK)
84 CloseHandle(m_ComPortHandle);
93 if (m_DeviceName.empty())
94 ss <<
"/dev/ttyS" <<
static_cast<unsigned int>(m_PortNumber) - 1;
99 m_FileDescriptor =
open(ss.str().c_str(), O_RDWR|O_NONBLOCK|O_EXCL);
100 if (m_FileDescriptor < 0)
103 fcntl(m_FileDescriptor, F_SETFL, 0);
104 tcflush(m_FileDescriptor, TCIOFLUSH);
105 if (this->ApplyConfiguration() !=
OK)
107 close(m_FileDescriptor);
121 ClearReceiveBuffer();
123 SetCommState(m_ComPortHandle, &m_PreviousDeviceControlBlock);
124 SetCommTimeouts(m_ComPortHandle, &m_PreviousTimeout);
125 SetCommMask(m_ComPortHandle, m_PreviousMask);
126 PurgeComm(m_ComPortHandle, PURGE_TXCLEAR | PURGE_RXCLEAR);
127 CloseHandle(m_ComPortHandle);
135 ClearReceiveBuffer();
137 close(m_FileDescriptor);
146 if (numberOfBytes == 0)
148 if (m_Connected ==
false)
155 DWORD numberOfBytesRead = 0;
156 char* buffer =
new char[numberOfBytes];
157 if (ReadFile(m_ComPortHandle, buffer, numberOfBytes, &numberOfBytesRead,
nullptr) != 0)
159 if (numberOfBytesRead > 0)
161 answer.assign(buffer, numberOfBytesRead);
163 if (numberOfBytesRead == numberOfBytes)
186 unsigned long bytesRead = 0;
187 unsigned long bytesLeft = numberOfBytes;
188 auto buffer =
new char[numberOfBytes];
190 while ((bytesLeft > 0) && (bytesRead < numberOfBytes))
192 int num =
read(m_FileDescriptor, &buffer[bytesRead], 1);
206 if (eol && *eol == buffer[bytesRead-1])
210 answer.assign(buffer, bytesRead);
214 if ( bytesRead == numberOfBytes ||
215 (eol && answer.size() > 0 && *eol == answer.at(answer.size()-1)) )
227 if (m_Connected ==
false)
234 DWORD bytesWritten = 0;
235 if (WriteFile(m_ComPortHandle, input.data(),
static_cast<DWORD
>(input.size()), &bytesWritten,
nullptr) == TRUE)
244 long bytesWritten = 0;
245 long bytesLeft = input.size();
247 while (bytesLeft > 0)
249 bytesWritten =
write(m_FileDescriptor, input.data() + bytesWritten, bytesLeft);
250 if (bytesWritten <= 0)
252 bytesLeft -= bytesWritten;
257 if (tcdrain(m_FileDescriptor) == -1)
267 return ApplyConfigurationWin();
269 return ApplyConfigurationUnix();
278int mitk::SerialCommunication::ApplyConfigurationWin()
284 if (GetCommState(m_ComPortHandle, &controlSettings) == 0)
289 std::ostringstream o;
290 o <<
"baud=" << m_BaudRate <<
" parity=" <<
static_cast<char>(m_Parity) <<
" data=" << m_DataBits <<
" stop=" << m_StopBits;
291 if (BuildCommDCBA(o.str().c_str(), &controlSettings) == 0)
294 if (m_HardwareHandshake == HardwareHandshakeOn)
296 controlSettings.fDtrControl = DTR_CONTROL_ENABLE;
297 controlSettings.fRtsControl = RTS_CONTROL_ENABLE;
298 controlSettings.fOutxCtsFlow = TRUE;
299 controlSettings.fRtsControl = RTS_CONTROL_HANDSHAKE;
303 controlSettings.fDtrControl = DTR_CONTROL_DISABLE;
304 controlSettings.fRtsControl = RTS_CONTROL_DISABLE;
305 controlSettings.fOutxCtsFlow = FALSE;
306 controlSettings.fRtsControl = RTS_CONTROL_DISABLE;
308 if (SetCommState(m_ComPortHandle, &controlSettings) == FALSE)
311 COMMTIMEOUTS timeouts;
313 timeouts.ReadIntervalTimeout = m_ReceiveTimeout;
314 timeouts.ReadTotalTimeoutMultiplier = 0;
315 timeouts.ReadTotalTimeoutConstant = m_ReceiveTimeout;
316 timeouts.WriteTotalTimeoutMultiplier = 0;
317 timeouts.WriteTotalTimeoutConstant = m_SendTimeout;
318 if (SetCommTimeouts(m_ComPortHandle, &timeouts) == FALSE)
321 PurgeComm(m_ComPortHandle, PURGE_TXCLEAR | PURGE_RXCLEAR);
334 struct termios termIOStructure;
335 if ( tcgetattr(m_FileDescriptor, &termIOStructure) != 0 )
338 cfmakeraw(&termIOStructure);
339 termIOStructure.c_cflag |= CLOCAL;
340 if (m_HardwareHandshake == HardwareHandshakeOn)
342 termIOStructure.c_cflag |= CRTSCTS;
343 termIOStructure.c_iflag &= ~(IXON|IXOFF);
347 termIOStructure.c_cflag &= ~CRTSCTS;
348 termIOStructure.c_iflag &= ~(IXON|IXOFF);
350 termIOStructure.c_cflag &= ~CSIZE;
354 termIOStructure.c_cflag |= CS7;
358 termIOStructure.c_cflag |= CS8;
363 termIOStructure.c_cflag |= CSTOPB;
367 termIOStructure.c_cflag &= ~CSTOPB;
372 termIOStructure.c_cflag |= (PARENB|PARODD);
375 termIOStructure.c_cflag |= PARENB;
376 termIOStructure.c_cflag &= ~PARODD;
382 termIOStructure.c_cflag &= ~PARENB;
423 case BaudRate1000000:
426 case BaudRate1152000:
432 case BaudRate1500000:
435 case BaudRate2000000:
438 case BaudRate2500000:
441 case BaudRate3000000:
444 case BaudRate3500000:
447 case BaudRate4000000:
452 MITK_WARN(
"mitk::SerialCommunication") <<
"Baud rate not recognized, using default of 9600 Baud.";
456 cfsetispeed(&termIOStructure, baudrate);
457 cfsetospeed(&termIOStructure, baudrate);
459 termIOStructure.c_cc[VMIN] = 0;
460 termIOStructure.c_cc[VTIME] = m_ReceiveTimeout / 100;
462 if (tcsetattr(m_FileDescriptor, TCSANOW, &termIOStructure) == 0)
476 SetCommBreak(m_ComPortHandle);
477 itksys::SystemTools::Delay(ms);
478 ClearCommBreak(m_ComPortHandle);
485 tcsendbreak(m_FileDescriptor, ms);
494 PurgeComm(m_ComPortHandle, PURGE_RXCLEAR);
497 tcflush(m_FileDescriptor, TCIFLUSH);
505 PurgeComm(m_ComPortHandle, PURGE_TXCLEAR);
508 tcflush(m_FileDescriptor, TCOFLUSH);
void ClearSendBuffer()
erase the send buffer of the serial interface
int ApplyConfigurationUnix()
Applies the configuration for Linux.
void SendBreak(unsigned int ms=400)
Send the break signal for ms milliseconds.
int OpenConnection()
Opens connection to the COM port with port number m_PortNumber or the device name m_DeviceName and al...
bool IsConnected()
Returns m_Connected.
int Send(const std::string &input, bool block=false)
Send the string input.
void CloseConnection()
Closes the connection.
int Receive(std::string &answer, unsigned int numberOfBytes, const char *eol=nullptr)
Read numberOfBytes characters from the serial interface.
int ApplyConfiguration()
configures the serial interface with all parameters
void ClearReceiveBuffer()
erase the receive buffer of the serial interface
~SerialCommunication() override
#define INVALID_HANDLE_VALUE
int open(const char *, int)
Opens a file descriptor.
int read(int, char *, size_t)
Read bytes from a file descriptor.
int errno
Contains the last error code.
int close(int)
Closes the file descriptor fd.
size_t write(int, const char *, size_t)
Writes count bytes from buf to the filedescriptor fd.