mavlink_core/connection/
direct_serial.rs

1//! Serial MAVLINK connection
2
3use crate::connectable::SerialConnectable;
4use crate::connection::MavConnection;
5use crate::peek_reader::PeekReader;
6use crate::{MavHeader, MavlinkVersion, Message};
7use core::ops::DerefMut;
8use std::io;
9use std::sync::Mutex;
10
11use crate::error::{MessageReadError, MessageWriteError};
12use serial::{prelude::*, SystemPort};
13
14#[cfg(not(feature = "signing"))]
15use crate::{read_versioned_msg, write_versioned_msg};
16#[cfg(feature = "signing")]
17use crate::{read_versioned_msg_signed, write_versioned_msg_signed, SigningConfig, SigningData};
18
19use super::Connectable;
20
21pub struct SerialConnection {
22    port: Mutex<PeekReader<SystemPort>>,
23    sequence: Mutex<u8>,
24    protocol_version: MavlinkVersion,
25    #[cfg(feature = "signing")]
26    signing_data: Option<SigningData>,
27}
28
29impl<M: Message> MavConnection<M> for SerialConnection {
30    fn recv(&self) -> Result<(MavHeader, M), MessageReadError> {
31        let mut port = self.port.lock().unwrap();
32        loop {
33            #[cfg(not(feature = "signing"))]
34            let result = read_versioned_msg(port.deref_mut(), self.protocol_version);
35            #[cfg(feature = "signing")]
36            let result = read_versioned_msg_signed(
37                port.deref_mut(),
38                self.protocol_version,
39                self.signing_data.as_ref(),
40            );
41            match result {
42                ok @ Ok(..) => {
43                    return ok;
44                }
45                Err(MessageReadError::Io(e)) => {
46                    if e.kind() == io::ErrorKind::UnexpectedEof {
47                        return Err(MessageReadError::Io(e));
48                    }
49                }
50                _ => {}
51            }
52        }
53    }
54
55    fn send(&self, header: &MavHeader, data: &M) -> Result<usize, MessageWriteError> {
56        let mut port = self.port.lock().unwrap();
57        let mut sequence = self.sequence.lock().unwrap();
58
59        let header = MavHeader {
60            sequence: *sequence,
61            system_id: header.system_id,
62            component_id: header.component_id,
63        };
64
65        *sequence = sequence.wrapping_add(1);
66
67        #[cfg(not(feature = "signing"))]
68        let result = write_versioned_msg(port.reader_mut(), self.protocol_version, header, data);
69        #[cfg(feature = "signing")]
70        let result = write_versioned_msg_signed(
71            port.reader_mut(),
72            self.protocol_version,
73            header,
74            data,
75            self.signing_data.as_ref(),
76        );
77        result
78    }
79
80    fn set_protocol_version(&mut self, version: MavlinkVersion) {
81        self.protocol_version = version;
82    }
83
84    fn protocol_version(&self) -> MavlinkVersion {
85        self.protocol_version
86    }
87
88    #[cfg(feature = "signing")]
89    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
90        self.signing_data = signing_data.map(SigningData::from_config)
91    }
92}
93
94impl Connectable for SerialConnectable {
95    fn connect<M: Message>(&self) -> io::Result<Box<dyn MavConnection<M> + Sync + Send>> {
96        let baud_rate = serial::core::BaudRate::from_speed(self.baud_rate);
97        let settings = serial::core::PortSettings {
98            baud_rate,
99            char_size: serial::Bits8,
100            parity: serial::ParityNone,
101            stop_bits: serial::Stop1,
102            flow_control: serial::FlowNone,
103        };
104
105        let mut port = serial::open(&self.port_name)?;
106        port.configure(&settings)?;
107
108        Ok(Box::new(SerialConnection {
109            port: Mutex::new(PeekReader::new(port)),
110            sequence: Mutex::new(0),
111            protocol_version: MavlinkVersion::V2,
112            #[cfg(feature = "signing")]
113            signing_data: None,
114        }))
115    }
116}