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, ReadVersion};
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    recv_any_version: bool,
26    #[cfg(feature = "signing")]
27    signing_data: Option<SigningData>,
28}
29
30impl<M: Message> MavConnection<M> for SerialConnection {
31    fn recv(&self) -> Result<(MavHeader, M), MessageReadError> {
32        let mut port = self.port.lock().unwrap();
33        loop {
34            let version = ReadVersion::from_conn_cfg::<_, M>(self);
35            #[cfg(not(feature = "signing"))]
36            let result = read_versioned_msg(port.deref_mut(), version);
37            #[cfg(feature = "signing")]
38            let result =
39                read_versioned_msg_signed(port.deref_mut(), version, self.signing_data.as_ref());
40            match result {
41                ok @ Ok(..) => {
42                    return ok;
43                }
44                Err(MessageReadError::Io(e)) => {
45                    if e.kind() == io::ErrorKind::UnexpectedEof {
46                        return Err(MessageReadError::Io(e));
47                    }
48                }
49                _ => {}
50            }
51        }
52    }
53
54    fn send(&self, header: &MavHeader, data: &M) -> Result<usize, MessageWriteError> {
55        let mut port = self.port.lock().unwrap();
56        let mut sequence = self.sequence.lock().unwrap();
57
58        let header = MavHeader {
59            sequence: *sequence,
60            system_id: header.system_id,
61            component_id: header.component_id,
62        };
63
64        *sequence = sequence.wrapping_add(1);
65
66        #[cfg(not(feature = "signing"))]
67        let result = write_versioned_msg(port.reader_mut(), self.protocol_version, header, data);
68        #[cfg(feature = "signing")]
69        let result = write_versioned_msg_signed(
70            port.reader_mut(),
71            self.protocol_version,
72            header,
73            data,
74            self.signing_data.as_ref(),
75        );
76        result
77    }
78
79    fn set_protocol_version(&mut self, version: MavlinkVersion) {
80        self.protocol_version = version;
81    }
82
83    fn protocol_version(&self) -> MavlinkVersion {
84        self.protocol_version
85    }
86
87    fn set_allow_recv_any_version(&mut self, allow: bool) {
88        self.recv_any_version = allow
89    }
90
91    fn allow_recv_any_version(&self) -> bool {
92        self.recv_any_version
93    }
94
95    #[cfg(feature = "signing")]
96    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
97        self.signing_data = signing_data.map(SigningData::from_config)
98    }
99}
100
101impl Connectable for SerialConnectable {
102    fn connect<M: Message>(&self) -> io::Result<Box<dyn MavConnection<M> + Sync + Send>> {
103        let baud_rate = serial::core::BaudRate::from_speed(self.baud_rate);
104        let settings = serial::core::PortSettings {
105            baud_rate,
106            char_size: serial::Bits8,
107            parity: serial::ParityNone,
108            stop_bits: serial::Stop1,
109            flow_control: serial::FlowNone,
110        };
111
112        let mut port = serial::open(&self.port_name)?;
113        port.configure(&settings)?;
114
115        Ok(Box::new(SerialConnection {
116            port: Mutex::new(PeekReader::new(port)),
117            sequence: Mutex::new(0),
118            protocol_version: MavlinkVersion::V2,
119            #[cfg(feature = "signing")]
120            signing_data: None,
121            recv_any_version: false,
122        }))
123    }
124}