18#include <linux/netlink.h>
19#include <linux/serial.h>
21#include <sys/select.h>
22#include <sys/socket.h>
65 uint32_t timeout_usec);
70 virtual size_t read(uint8_t* buffer,
size_t max_length);
71 virtual size_t write(
const uint8_t* data,
size_t length);
77 bool configure_port(
int fd);
78 bool wait_readable(uint32_t timeout_us);
79 bool wait_writable(uint32_t timeout_us);
82 std::string device_name_;
87 uint32_t flowcontrol_;
88 uint32_t byte_time_us_;
90 uint32_t timeout_usec_;
96SerialStream::SerialStream(
const char* device_name, speed_t baud_rate,
97 uint32_t timeout_usec)
98 : device_name_(device_name),
99 baud_rate_(baud_rate),
104 timeout_usec_(timeout_usec),
108 if (device_name_.empty()) {
115void SerialStream::open(
void) {
117 fd = ::open(device_name_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
127 AERROR <<
"Open device " << device_name_
128 <<
" failed, error: " << strerror(errno);
133 if (!configure_port(fd)) {
142bool SerialStream::configure_port(
int fd) {
147 struct termios options;
148 if (tcgetattr(fd, &options) == -1) {
149 AERROR <<
"tcgetattr failed.";
154 options.c_cflag |= (tcflag_t)(CLOCAL | CREAD);
155 options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
158 options.c_oflag &= (tcflag_t) ~(OPOST);
159 options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK);
162 options.c_iflag &= (tcflag_t)~IUCLC;
166 options.c_iflag &= (tcflag_t)~PARMRK;
170 ::cfsetspeed(&options, baud_rate_);
172 ::cfsetispeed(&options, baud_rate_);
173 ::cfsetospeed(&options, baud_rate_);
177 options.c_cflag &= (tcflag_t)~CSIZE;
180 options.c_cflag |= CS8;
183 options.c_cflag &= (tcflag_t) ~(CSTOPB);
186 options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP);
187 options.c_cflag &= (tcflag_t) ~(PARENB | PARODD);
192 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);
194 options.c_iflag &= (tcflag_t) ~(IXON | IXOFF);
199 options.c_cflag &=
static_cast<uint64_t
>(~(CRTSCTS));
200#elif defined CNEW_RTSCTS
201 options.c_cflag &=
static_cast<uint64_t
>(~(CNEW_RTSCTS));
203#error "OS Support seems wrong."
210 options.c_cc[VMIN] = 0;
211 options.c_cc[VTIME] = 0;
214 ::tcsetattr(fd, TCSANOW, &options);
217 uint32_t bit_time_us =
static_cast<uint32_t
>(1e6 / 115200);
218 byte_time_us_ = bit_time_us * (1 + bytesize_ + parity_ + stopbits_);
241void SerialStream::close(
void) {
260void SerialStream::check_remove() {
262 ssize_t nsent =
::write(fd_, &data, 0);
264 AERROR <<
"Serial stream detect write failed, error: " << strerror(errno);
269 AERROR <<
"Device " << device_name_ <<
" removed.";
281 AINFO <<
"Connect " << device_name_ <<
" success.";
284 ssize_t bytes_read = 0;
285 ssize_t bytes_current_read = 0;
287 wait_readable(10000);
289 while (max_length > 0) {
290 bytes_current_read =
::read(fd_, buffer, max_length);
291 if (bytes_current_read < 0) {
295 bytes_current_read = 0;
300 AERROR <<
"Serial stream read data failed, error: "
304 AINFO <<
"Reconnect " << device_name_ <<
" success.";
305 bytes_current_read = 0;
310 AERROR <<
"Serial stream read data failed, error: " << strerror(errno)
311 <<
", errno: " << errno;
318 if (bytes_current_read == 0) {
325 max_length -= bytes_current_read;
326 buffer += bytes_current_read;
327 bytes_read += bytes_current_read;
338 AINFO <<
"Connect " << device_name_ <<
" success.";
341 size_t total_nsent = 0;
342 size_t delay_times = 0;
344 while ((length > 0) && (delay_times < 5)) {
345 ssize_t nsent =
::write(fd_, data, length);
347 AERROR <<
"Serial stream write data failed, error: " << strerror(errno);
358 AINFO <<
"Reconnect " << device_name_ <<
"success.";
371 if (!wait_writable(byte_time_us_)) {
378 total_nsent += nsent;
386bool SerialStream::wait_readable(uint32_t timeout_us) {
391 FD_SET(fd_, &readfds);
393 timeout_ts.tv_sec = timeout_us / 1000000;
394 timeout_ts.tv_nsec = (timeout_us % 1000000) * 1000;
395 int r = pselect(fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL);
401 if (!FD_ISSET(fd_, &readfds)) {
408bool SerialStream::wait_writable(uint32_t timeout_us) {
413 FD_SET(fd_, &writefds);
415 timeout_ts.tv_sec = timeout_us / 1000000;
416 timeout_ts.tv_nsec = (timeout_us % 1000000) * 1000;
417 int r = pselect(fd_ + 1, NULL, &writefds, NULL, &timeout_ts, NULL);
423 if (!FD_ISSET(fd_, &writefds)) {
431 uint32_t timeout_usec) {
433 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)