Skip to main content

mavlink_core/connection/direct_serial/
sync.rs

1//! Serial MAVLINK connection
2
3use super::config::SerialConfig;
4
5use crate::Dialect;
6use crate::MavlinkReader;
7use crate::connection::sync::{Connectable, DialectConnection, SyncTransport, Transport};
8use serialport::{DataBits, FlowControl, Parity, StopBits};
9use std::io;
10use std::sync::Mutex;
11use std::time::Duration;
12
13#[cfg(windows)]
14use serialport::COMPort as NativePort;
15#[cfg(unix)]
16use serialport::TTYPort as NativePort;
17
18pub struct SerialConnection {
19    // Separate ports for reading and writing as it's safe to use concurrently.
20    // See the official ref: https://github.com/serialport/serialport-rs/blob/321f85e1886eaa1302aef8a600a631bc1c88703a/examples/duplex.rs
21    read_port: Mutex<MavlinkReader<NativePort>>,
22    write_port: Mutex<NativePort>,
23}
24
25impl SyncTransport for SerialConnection {
26    type Reader = NativePort;
27    type Writer = NativePort;
28
29    fn reader(&self) -> std::sync::MutexGuard<'_, MavlinkReader<Self::Reader>> {
30        self.read_port.lock().unwrap()
31    }
32
33    fn lock_writer(&self) -> Option<std::sync::MutexGuard<'_, Self::Writer>> {
34        Some(self.write_port.lock().unwrap())
35    }
36
37    fn retry_receive(&self, error: &crate::error::MessageReadError) -> bool {
38        !matches!(error, crate::error::MessageReadError::Io(error) if error.kind() == io::ErrorKind::UnexpectedEof)
39    }
40}
41
42impl SerialConfig {
43    pub(crate) fn open(&self) -> io::Result<SerialConnection> {
44        let read_port = serialport::new(&self.port_name, self.baud_rate)
45            .data_bits(DataBits::Eight)
46            .parity(Parity::None)
47            .stop_bits(StopBits::One)
48            .flow_control(FlowControl::None)
49            .timeout(self.timeout.unwrap_or(Duration::from_millis(1)))
50            .open_native()?;
51        let write_port = read_port.try_clone_native()?;
52        Ok(SerialConnection {
53            read_port: Mutex::new(MavlinkReader::with_capacity(
54                self.buffer_capacity(),
55                read_port,
56            )),
57            write_port: Mutex::new(write_port),
58        })
59    }
60}
61
62impl Connectable for SerialConfig {
63    fn connect_with_dialect<D: Dialect + Send + Sync>(
64        &self,
65        dialect: D,
66    ) -> io::Result<DialectConnection<D>> {
67        Ok(DialectConnection::new(
68            Transport::Serial(self.open()?),
69            dialect,
70        ))
71    }
72}