24 #if defined(__linux__)
25 #include <linux/serial.h>
30 using boost::system::error_code;
31 using boost::asio::io_service;
32 using boost::asio::buffer;
33 using mavlink::mavlink_message_t;
36 #define PFX "mavconn: serial"
37 #define PFXd PFX "%zu: "
41 std::string device,
unsigned baudrate,
bool hwflow) :
44 serial_dev(io_service),
45 tx_in_progress(false),
49 using SPB = boost::asio::serial_port_base;
54 serial_dev.open(device);
57 serial_dev.set_option(SPB::baud_rate(baudrate));
58 serial_dev.set_option(SPB::character_size(8));
59 serial_dev.set_option(SPB::parity(SPB::parity::none));
60 serial_dev.set_option(SPB::stop_bits(SPB::stop_bits::one));
62 #if BOOST_ASIO_VERSION >= 101200 || !defined(__linux__)
64 serial_dev.set_option(SPB::flow_control( (hwflow) ? SPB::flow_control::hardware : SPB::flow_control::none));
65 #elif BOOST_ASIO_VERSION < 101200 && defined(__linux__)
70 int fd = serial_dev.native_handle();
77 tio.c_iflag &= ~(IXOFF | IXON);
78 tio.c_cflag |= CRTSCTS;
80 tio.c_iflag &= ~(IXOFF | IXON);
81 tio.c_cflag &= ~CRTSCTS;
88 tcsetattr(fd, TCSANOW, &tio);
92 #if defined(__linux__)
95 int fd = serial_dev.native_handle();
97 struct serial_struct ser_info;
98 ioctl(fd, TIOCGSERIAL, &ser_info);
100 ser_info.flags |= ASYNC_LOW_LATENCY;
102 ioctl(fd, TIOCSSERIAL, &ser_info);
106 catch (boost::system::system_error &err) {
107 throw DeviceError(
"serial", err);
117 const ReceivedCb &cb_handle_message,
118 const ClosedCb &cb_handle_closed_port)
164 throw std::length_error(
"MAVConnSerial::send_bytes: TX queue overflow");
166 tx_q.emplace_back(bytes, length);
173 assert(message !=
nullptr);
186 throw std::length_error(
"MAVConnSerial::send_message: TX queue overflow");
188 tx_q.emplace_back(message);
206 throw std::length_error(
"MAVConnSerial::send_message: TX queue overflow");
215 auto sthis = shared_from_this();
218 [sthis] (error_code error,
size_t bytes_transferred) {
225 sthis->parse_buffer(
PFX, sthis->rx_buf.data(), sthis->rx_buf.size(), bytes_transferred);
240 auto sthis = shared_from_this();
241 auto &buf_ref =
tx_q.front();
243 buffer(buf_ref.dpos(), buf_ref.nbytes()),
244 [sthis, &buf_ref] (error_code error,
size_t bytes_transferred) {
245 assert(bytes_transferred <= buf_ref.len);
248 CONSOLE_BRIDGE_logError(PFXd
"write: %s", sthis->conn_id, error.message().c_str());
253 sthis->iostat_tx_add(bytes_transferred);
256 if (sthis->tx_q.empty()) {
257 sthis->tx_in_progress = false;
261 buf_ref.pos += bytes_transferred;
262 if (buf_ref.nbytes() == 0) {
263 sthis->tx_q.pop_front();
266 if (!sthis->tx_q.empty())
267 sthis->do_write(
false);
269 sthis->tx_in_progress =
false;