53 # include <sys/time.h> 64 #undef SERIAL_DUMP_DATA 71 : m_dev_name(strdup(dev_name))
72 , m_serial_flags(flags)
75 m_com = INVALID_HANDLE_VALUE;
88 m_com = INVALID_HANDLE_VALUE;
101 #if defined _SYSTEM_LINUX_ 122 if (tcgetattr(m_file_descr, &m_io_set_old) < 0)
126 "Cannot get serial device m_status '" <<
m_dev_name <<
"'. Status (" 137 io_set_new = m_io_set_old;
141 io_set_new.c_oflag = 0;
142 io_set_new.c_iflag = IGNPAR;
143 io_set_new.c_lflag = 0;
144 io_set_new.c_cc[VMIN] = 1;
145 io_set_new.c_cc[VTIME] = 0;
148 if (tcsetattr(m_file_descr, TCSANOW, &io_set_new) < 0)
152 "Serial(" <<
m_dev_name <<
") Error>> tcsetattr failed. Status (" 164 "Serial(" <<
m_dev_name <<
") setting hardware modem control flags to 0x" 168 int modem_control_flags = 0;
171 modem_control_flags |= TIOCM_DTR;
175 modem_control_flags |= TIOCM_RTS;
178 ioctl(m_file_descr, TIOCMSET, modem_control_flags);
182 #elif defined _SYSTEM_WIN32_ 184 m_read_buffer_fill = 0;
189 m_dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
190 if (m_com == INVALID_HANDLE_VALUE)
194 "Serial(" <<
m_dev_name <<
"): ERROR>> open port failed (" 195 << StatusText().c_str() <<
").");
202 if (!SetupComm(m_com, 0x4000, 0x4000))
206 "Serial(" <<
m_dev_name <<
"): ERROR>> SetupComm failed (" 207 << StatusText().c_str() <<
").");
215 memset(&dcb, 0,
sizeof(DCB));
218 if (!GetCommState(m_com, &dcb))
222 "Serial(" <<
m_dev_name <<
"): ERROR>> GetCommState failed (" 223 << StatusText().c_str() <<
").");
233 if (!SetCommState(m_com, &dcb))
237 "Serial(" <<
m_dev_name <<
"): ERROR>> SetCommState failed (" 238 << StatusText().c_str() <<
").");
251 unsigned char* c_data =
static_cast<unsigned char*
>(data);
252 printf(
"Serial::DumpData: ");
253 for (
size_t i = 0; i < length; ++i)
255 printf(
"%02X ",
int(c_data[i]));
270 #if defined _SYSTEM_LINUX_ 272 if (m_file_descr < 0)
275 struct termios io_set;
278 if (tcgetattr(m_file_descr, &io_set) < 0)
282 "Serial(" <<
m_dev_name <<
"): Error>> tcgetattr failed. Status (" 290 io_set.c_cflag &= ~CBAUD;
292 io_set.c_cflag |= SerialFlags::cFlags(speed);
295 if (tcsetattr(m_file_descr, TCSANOW, &io_set) < 0)
299 "Serial(" <<
m_dev_name <<
"): Error>> tcsetattr failed. Status (" 316 #ifdef _SYSTEM_DARWIN_ 322 #ifdef _SYSTEM_WIN32_ 326 if (!PurgeComm(m_com, PURGE_RXCLEAR) || !PurgeComm(m_com, PURGE_TXCLEAR))
330 "Serial(" <<
m_dev_name <<
"): ERROR>> PurgeComm failed (" 331 << StatusText().c_str() <<
").");
337 memset(&dcb, 0,
sizeof(DCB));
340 if (!GetCommState(m_com, &dcb))
344 "Serial(" <<
m_dev_name <<
"): ERROR>> GetCommState failed (" 345 << StatusText().c_str() <<
").");
355 if (!SetCommState(m_com, &dcb))
359 "Serial(" <<
m_dev_name <<
"): ERROR>> SetCommState failed (" 360 << StatusText().c_str() <<
").");
372 #ifdef _SYSTEM_WIN32_ 376 if (PurgeComm(m_com, PURGE_RXCLEAR))
378 m_read_buffer_fill = 0;
384 "Serial(" <<
m_dev_name <<
"): ERROR>> PurgeComm failed (" 385 << StatusText().c_str() <<
").");
390 #elif defined _SYSTEM_LINUX_ 392 if (tcflush(m_file_descr, TCIFLUSH) != 0)
405 #ifdef _SYSTEM_WIN32_ 409 if (PurgeComm(m_com, PURGE_TXCLEAR))
411 m_read_buffer_fill = 0;
417 "Serial(" <<
m_dev_name <<
"): ERROR>> PurgeComm failed (" 418 << StatusText().c_str() <<
").");
423 #elif defined _SYSTEM_LINUX_ 425 if (tcflush(m_file_descr, TCOFLUSH) != 0)
438 #if defined _SYSTEM_LINUX_ 439 if (m_file_descr < 0)
442 ssize_t bytes_out = 0;
446 if ((bytes_out = ::
write(m_file_descr, (
char*)data, size)) < 0)
451 <<
"): Error on writing. Status (" <<
m_status <<
":" 464 #elif defined _SYSTEM_WIN32_ 466 assert(m_com != INVALID_HANDLE_VALUE);
469 if (!WriteFile(m_com, data, size, &bytes_written, NULL))
473 "Serial(" <<
m_dev_name <<
"): ERROR>> could not write data (" 474 << StatusText().c_str() <<
").");
481 # ifdef SERIAL_DUMP_DATA 482 DumpData(data, bytes_written);
492 ssize_t
Serial::read(
void* data, ssize_t size,
unsigned long time,
bool return_on_less_data)
495 auto end_time = std::chrono::high_resolution_clock::now() + std::chrono::microseconds(time);
497 #if defined _SYSTEM_LINUX_ 498 if (m_file_descr < 0)
501 std::chrono::duration<double, std::milli> tz;
503 ssize_t bytes_read = 0;
504 ssize_t bytes_read_inc;
506 char* buffer = (
char*)data;
517 tz = end_time - std::chrono::high_resolution_clock::now();
519 if (tz < std::chrono::microseconds(1))
521 tz = std::chrono::microseconds(1);
527 FD_SET(m_file_descr, &fds);
528 timeval select_timeout = {0,
529 std::chrono::duration_cast<std::chrono::microseconds>(tz).count()};
531 if ((select_return = select(FD_SETSIZE, &fds, 0, 0, &select_timeout)) > 0)
534 if (return_on_less_data)
536 if ((bytes_read_inc = ::
read(m_file_descr, &buffer[bytes_read], size - bytes_read)) < 0)
541 <<
":" << strerror(-
m_status) <<
")");
547 if (bytes_read_inc > 0)
549 bytes_read += bytes_read_inc;
551 if (bytes_read == size)
561 if (ioctl(m_file_descr, FIONREAD, &bytes_read_inc) < 0)
565 "Error on ioctl FIONREAD '" <<
m_dev_name <<
"'. Status (" 575 if (bytes_read_inc >= size)
577 if ((bytes_read = ::
read(m_file_descr, buffer, size)) < 0)
582 <<
":" << strerror(-
m_status) <<
")");
597 else if (select_return < 0)
609 while (std::chrono::high_resolution_clock::now() < end_time);
618 #ifdef _SYSTEM_DARWIN_ 624 #ifdef _SYSTEM_WIN32_ 625 assert(m_com != INVALID_HANDLE_VALUE);
630 COMMTIMEOUTS timeout;
631 timeout.ReadIntervalTimeout = time / 1000;
632 timeout.ReadTotalTimeoutMultiplier = 1;
633 timeout.ReadTotalTimeoutConstant = time / 1000;
634 timeout.WriteTotalTimeoutMultiplier = 1;
635 timeout.WriteTotalTimeoutConstant = MAXDWORD;
636 if (!SetCommTimeouts(m_com, &timeout))
640 "Serial(" <<
m_dev_name <<
"): ERROR>> setting read timeout failed (" 641 << StatusText().c_str() <<
")");
647 if (m_read_buffer_fill <= size &&
m_status == 0)
649 DWORD bytes_received = 0;
650 size_t bytes_remaining = (m_read_buffer_fill < size ? size - m_read_buffer_fill : 0);
651 auto now std::chrono::high_resolution_clock::now();
655 m_com, m_read_buffer + m_read_buffer_fill, bytes_remaining, &bytes_received, NULL))
657 m_read_buffer_fill += bytes_received;
658 if (bytes_remaining > bytes_received)
660 bytes_remaining -= bytes_received;
669 DWORD error = GetLastError();
670 if (error != ERROR_TIMEOUT)
674 "Serial(" <<
m_dev_name <<
"): ERROR>> error during read (" 675 << StatusText().c_str() <<
")");
680 now = std::chrono::high_resolution_clock::now();
681 }
while (
m_status == 0 && !return_on_less_data && bytes_remaining && now < end_time);
683 if (
m_status == 0 && !return_on_less_data && bytes_remaining && now >= end_time)
687 "Serial(" <<
m_dev_name <<
"): ERROR>> error during read (" 688 << StatusText().c_str() <<
")");
695 ssize_t bytes_received;
698 bytes_received = std::min(size, m_read_buffer_fill);
699 memcpy(data, m_read_buffer, bytes_received);
702 for (ssize_t write_index = 0, read_index = bytes_received; read_index < m_read_buffer_fill;
703 ++write_index, ++read_index)
705 m_read_buffer[write_index] = m_read_buffer[read_index];
707 m_read_buffer_fill -= bytes_received;
709 # ifdef SERIAL_DUMP_DATA 710 DumpData(data, bytes_received);
720 #if defined _SYSTEM_LINUX_ 722 #elif defined _SYSTEM_WIN32_ 723 LPVOID msg_buff = NULL;
724 DWORD res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
725 FORMAT_MESSAGE_IGNORE_INSERTS,
728 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
735 result = (LPCTSTR)msg_buff;
740 result =
"fatal internal error";
744 return "Plattform not supported!";
750 #ifdef _SYSTEM_LINUX_ 751 return m_file_descr >= 0;
752 #elif defined _SYSTEM_WIN32_ 753 return m_com != INVALID_HANDLE_VALUE;
762 #ifdef _SYSTEM_LINUX_ 763 if (m_file_descr >= 0)
767 if (tcsetattr(m_file_descr, TCSANOW, &m_io_set_old) < 0)
771 "Serial(" <<
m_dev_name <<
") Error>> tcsetattr failed. Status (" 777 if (::
close(m_file_descr) < 0)
781 "Serial>> Error closing serial " <<
m_dev_name <<
". Status (" 793 #ifdef _SYSTEM_WIN32_ 794 if (m_com != INVALID_HANDLE_VALUE)
797 m_com = INVALID_HANDLE_VALUE;
ssize_t read(void *data, ssize_t size, unsigned long time=100, bool return_on_less_data=true)
#define SVH_LOG_INFO_STREAM(NAME, M)
void setBaudRate(BaudRate baud_rate)
Serial(const char *dev_name, const SerialFlags &flags)
ssize_t write(const void *data, ssize_t size)
#define SVH_LOG_DEBUG_STREAM(NAME, M)
std::string statusText() const
Contains a class that enables access to serial devices.
BaudRate getBaudRate() const
ModemControlFlags getModemControlFlags() const
void dumpData(void *data, size_t length)
int changeBaudrate(SerialFlags::BaudRate speed)
SerialFlags m_serial_flags
#define SVH_LOG_WARN_STREAM(NAME, M)
Short description of tSerialFlags.