19#include <sys/select.h>
20#include <sys/socket.h>
63 uint32_t timeout_usec);
68 virtual size_t read(uint8_t* buffer,
size_t max_length);
69 virtual size_t write(
const uint8_t* data,
size_t length);
75 bool configure_port(
int fd);
76 bool wait_readable(uint32_t timeout_us);
77 bool wait_writable(uint32_t timeout_us);
80 std::string device_name_;
85 uint32_t flowcontrol_;
86 uint32_t byte_time_us_;
88 uint32_t timeout_usec_;
94SerialStream::SerialStream(
const char* device_name, speed_t baud_rate,
95 uint32_t timeout_usec)
96 : device_name_(device_name),
97 baud_rate_(baud_rate),
102 timeout_usec_(timeout_usec),
106 if (device_name_.empty()) {
113void SerialStream::open(
void) {
115 fd = ::open(device_name_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
125 AERROR <<
"Open device " << device_name_
126 <<
" failed, error: " << strerror(errno);
131 if (!configure_port(fd)) {
140bool SerialStream::configure_port(
int fd) {
145 struct termios options;
146 if (tcgetattr(fd, &options) == -1) {
147 AERROR <<
"tcgetattr failed.";
152 options.c_cflag |= (tcflag_t)(CLOCAL | CREAD);
153 options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
156 options.c_oflag &= (tcflag_t) ~(OPOST);
157 options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
160 options.c_iflag &= (tcflag_t)~IUCLC;
164 options.c_iflag &= (tcflag_t)~PARMRK;
168 ::cfsetspeed(&options, baud_rate_);
170 ::cfsetispeed(&options, baud_rate_);
171 ::cfsetospeed(&options, baud_rate_);
175 options.c_cflag &= (tcflag_t)~CSIZE;
178 options.c_cflag |= CS8;
181 options.c_cflag &= (tcflag_t) ~(CSTOPB);
184 options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
185 options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
190 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
192 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
197 options.c_cflag &=
static_cast<uint64_t
>(~(CRTSCTS));
198#elif defined CNEW_RTSCTS
199 options.c_cflag &=
static_cast<uint64_t
>(~(CNEW_RTSCTS));
201#error "OS Support seems wrong."
208 options.c_cc[VMIN] = 0;
209 options.c_cc[VTIME] = 0;
212 ::tcsetattr(fd, TCSANOW, &options);
215 uint32_t bit_time_us =
static_cast<uint32_t
>(1e6 / 115200);
216 byte_time_us_ = bit_time_us * (1 + bytesize_ + parity_ + stopbits_);
239void SerialStream::close(
void) {
258void SerialStream::check_remove() {
260 ssize_t nsent =
::write(fd_, &data, 0);
262 AERROR <<
"Serial stream detect write failed, error: " << strerror(errno);
267 AERROR <<
"Device " << device_name_ <<
" removed.";
279 AINFO <<
"Connect " << device_name_ <<
" success.";
282 ssize_t bytes_read = 0;
283 ssize_t bytes_current_read = 0;
287 while (max_length > 0) {
288 bytes_current_read =
::read(fd_, buffer, max_length);
289 if (bytes_current_read < 0) {
293 bytes_current_read = 0;
298 AERROR <<
"Serial stream read data failed, error: "
302 AINFO <<
"Reconnect " << device_name_ <<
" success.";
303 bytes_current_read = 0;
308 AERROR <<
"Serial stream read data failed, error: " << strerror(errno)
309 <<
", errno: " << errno;
316 if (bytes_current_read == 0) {
323 max_length -= bytes_current_read;
324 buffer += bytes_current_read;
325 bytes_read += bytes_current_read;
336 AINFO <<
"Connect " << device_name_ <<
" success.";
339 size_t total_nsent = 0;
340 size_t delay_times = 0;
342 while ((length > 0) && (delay_times < 5)) {
343 ssize_t nsent =
::write(fd_, data, length);
345 AERROR <<
"Serial stream write data failed, error: " << strerror(errno);
356 AINFO <<
"Reconnect " << device_name_ <<
"success.";
369 if (!wait_writable(byte_time_us_)) {
376 total_nsent += nsent;
384bool SerialStream::wait_readable(uint32_t timeout_us) {
389 FD_SET(fd_, &readfds);
391 timeout_ts.tv_sec = timeout_us / 1000000;
392 timeout_ts.tv_nsec = (timeout_us % 1000000) * 1000;
393 int r = pselect(fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL);
399 if (!FD_ISSET(fd_, &readfds)) {
406bool SerialStream::wait_writable(uint32_t timeout_us) {
411 FD_SET(fd_, &writefds);
413 timeout_ts.tv_sec = timeout_us / 1000000;
414 timeout_ts.tv_nsec = (timeout_us % 1000000) * 1000;
415 int r = pselect(fd_ + 1, NULL, &writefds, NULL, &timeout_ts, NULL);
421 if (!FD_ISSET(fd_, &writefds)) {
429 uint32_t timeout_usec) {
431 return baud == 0 ? nullptr
virtual bool Disconnect()
virtual size_t write(const uint8_t *data, size_t length)
virtual size_t read(uint8_t *buffer, size_t max_length)
static Stream * create_serial(const char *device_name, uint32_t baud_rate, uint32_t timeout_usec=0)
speed_t get_serial_baudrate(uint32_t rate)