mavlink_core/connection/
direct_serial.rs1use 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}