bt_rfcomm/frame/mux_commands/
remote_port_negotiation.rs
1use bitfield::bitfield;
6use packet_encoding::{Decodable, Encodable};
7
8use crate::frame::FrameParseError;
9use crate::DLCI;
10
11const REMOTE_PORT_NEGOTIATION_SHORT_LENGTH: usize = 1;
14
15const REMOTE_PORT_NEGOTIATION_LONG_LENGTH: usize = 8;
19
20const REMOTE_PORT_NEGOTIATION_VALUES_LENGTH: usize = 7;
23
24bitfield! {
25 struct RpnAddressField(u8);
26 impl Debug;
27 pub bool, ea_bit, set_ea_bit: 0;
28 pub bool, cr_bit, set_cr_bit: 1;
29 pub u8, dlci_raw, set_dlci: 7, 2;
30}
31
32impl RpnAddressField {
33 fn dlci(&self) -> Result<DLCI, FrameParseError> {
34 DLCI::try_from(self.dlci_raw())
35 }
36}
37
38const PORT_VALUES_UNANIMOUS_ACCEPT_MASK: u16 = 0b0011111101111111;
43
44bitfield! {
45 pub struct PortValues([u8]);
46 impl Debug;
47 pub u8, baud_rate, set_baud_rate: 7, 0;
48 pub u8, data_bits, set_data_bits: 9, 8;
49 pub bool, stop_bit, set_stop_bit: 10;
50 pub bool, parity, set_parity: 11;
51 pub u8, parity_type, set_parity_type: 13, 12;
52 pub u8, flow_control, set_flow_control: 21, 16;
53 pub u8, xon_character, set_xon_character: 31, 24;
54 pub u8, xoff_character, set_xoff_character: 39, 32;
55 pub u16, mask, set_mask: 55, 40;
56}
57
58impl PartialEq for PortValues<[u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]> {
59 fn eq(&self, other: &Self) -> bool {
60 self.0 == other.0
61 }
62}
63
64impl Clone for PortValues<[u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]> {
65 fn clone(&self) -> Self {
66 Self(self.0.clone())
67 }
68}
69
70impl Default for PortValues<[u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]> {
71 fn default() -> Self {
76 let mut values = PortValues([0; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]);
77 values.set_baud_rate(0x03);
78 values.set_data_bits(0b11);
79 values.set_stop_bit(false);
80 values.set_parity(false);
81 values.set_parity_type(0); values.set_flow_control(0x00);
83 values.set_xon_character(0x01);
84 values.set_xoff_character(0x03);
85 values.set_mask(0x00); values
87 }
88}
89
90#[derive(Clone, Debug, PartialEq)]
93pub struct RemotePortNegotiationParams {
94 pub dlci: DLCI,
95 pub port_values: Option<PortValues<[u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]>>,
97}
98
99impl RemotePortNegotiationParams {
100 pub fn response(&self) -> Self {
107 let port_values =
108 self.port_values.clone().map_or_else(PortValues::default, |mut values| {
109 values.set_mask(PORT_VALUES_UNANIMOUS_ACCEPT_MASK);
112 values
113 });
114 Self { dlci: self.dlci, port_values: Some(port_values) }
115 }
116}
117
118impl Decodable for RemotePortNegotiationParams {
119 type Error = FrameParseError;
120
121 fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
122 if buf.len() != REMOTE_PORT_NEGOTIATION_SHORT_LENGTH
123 && buf.len() != REMOTE_PORT_NEGOTIATION_LONG_LENGTH
124 {
125 return Err(FrameParseError::InvalidBufferLength(
126 REMOTE_PORT_NEGOTIATION_SHORT_LENGTH,
127 buf.len(),
128 ));
129 }
130
131 let address_field = RpnAddressField(buf[0]);
133 let dlci = address_field.dlci()?;
134
135 let port_values = if buf.len() == REMOTE_PORT_NEGOTIATION_SHORT_LENGTH {
137 None
138 } else {
139 let mut b = [0; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH];
140 b.copy_from_slice(&buf[1..REMOTE_PORT_NEGOTIATION_LONG_LENGTH]);
141 Some(PortValues(b))
142 };
143
144 Ok(RemotePortNegotiationParams { dlci, port_values })
145 }
146}
147
148impl Encodable for RemotePortNegotiationParams {
149 type Error = FrameParseError;
150
151 fn encoded_len(&self) -> usize {
152 if self.port_values.is_some() {
153 REMOTE_PORT_NEGOTIATION_LONG_LENGTH
154 } else {
155 REMOTE_PORT_NEGOTIATION_SHORT_LENGTH
156 }
157 }
158
159 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
160 if buf.len() < self.encoded_len() {
161 return Err(FrameParseError::BufferTooSmall);
162 }
163
164 let mut address_field = RpnAddressField(0);
166 address_field.set_ea_bit(true);
167 address_field.set_cr_bit(true);
168 address_field.set_dlci(u8::from(self.dlci));
169 buf[0] = address_field.0;
170
171 if let Some(port_values) = &self.port_values {
172 buf[1..REMOTE_PORT_NEGOTIATION_LONG_LENGTH].copy_from_slice(&port_values.0);
173 }
174
175 Ok(())
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182
183 use assert_matches::assert_matches;
184
185 #[test]
186 fn test_decode_rpn_invalid_buf() {
187 let buf = [0x00, 0x01, 0x02]; assert_matches!(
189 RemotePortNegotiationParams::decode(&buf[..]),
190 Err(FrameParseError::InvalidBufferLength(REMOTE_PORT_NEGOTIATION_SHORT_LENGTH, 3))
191 );
192 }
193
194 #[test]
195 fn test_decode_rpn_invalid_dlci() {
196 let buf = [
197 0b00000111, ];
199 assert_matches!(
200 RemotePortNegotiationParams::decode(&buf[..]),
201 Err(FrameParseError::InvalidDLCI(1))
202 );
203 }
204
205 #[test]
206 fn test_decode_rpn_short_command() {
207 let buf = [
208 0b00011111, ];
210 let expected =
211 RemotePortNegotiationParams { dlci: DLCI::try_from(7).unwrap(), port_values: None };
212 assert_eq!(RemotePortNegotiationParams::decode(&buf[..]).unwrap(), expected);
213 }
214
215 #[test]
216 fn test_decode_rpn_long_command() {
217 let port_values_buf: [u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH] = [
218 0b00000001, 0b00101011, 0b00011010, 0b00000001, 0b00000011, 0b10000001, 0b00000001, ];
226 let buf = vec![
227 0b00011111, ];
229 let buf = [buf, port_values_buf.to_vec()].concat();
230 let expected = RemotePortNegotiationParams {
231 dlci: DLCI::try_from(7).unwrap(),
232 port_values: Some(PortValues(port_values_buf)),
233 };
234 let decoded = RemotePortNegotiationParams::decode(&buf[..]).unwrap();
235 assert_eq!(decoded, expected);
236
237 let decoded_port_values = decoded.port_values.unwrap();
238 assert_eq!(decoded_port_values.baud_rate(), 1);
239 assert_eq!(decoded_port_values.data_bits(), 0b11);
240 assert_eq!(decoded_port_values.stop_bit(), false);
241 assert_eq!(decoded_port_values.parity(), true);
242 assert_eq!(decoded_port_values.parity_type(), 2);
243 assert_eq!(decoded_port_values.flow_control(), 26);
244 assert_eq!(decoded_port_values.xon_character(), 1);
245 assert_eq!(decoded_port_values.xoff_character(), 3);
246 assert_eq!(decoded_port_values.mask(), 385);
247 }
248
249 #[test]
250 fn test_encode_rpn_invalid_buf() {
251 let port_values_buf: [u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH] =
252 [0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000];
253 let command = RemotePortNegotiationParams {
254 dlci: DLCI::try_from(7).unwrap(),
255 port_values: Some(PortValues(port_values_buf)),
256 };
257 let mut buf = [];
258 assert_matches!(command.encode(&mut buf), Err(FrameParseError::BufferTooSmall));
259 }
260
261 #[test]
262 fn test_encode_rpn_short_command() {
263 let command =
264 RemotePortNegotiationParams { dlci: DLCI::try_from(2).unwrap(), port_values: None };
265 let mut buf = vec![0; command.encoded_len()];
266 let expected = [0b00001011]; assert!(command.encode(&mut buf).is_ok());
268 assert_eq!(buf, expected);
269 }
270
271 #[test]
272 fn test_encode_rpn_long_command() {
273 let port_values_buf: [u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH] = [
274 0b00010000, 0b00111100, 0b00000010, 0b00000001, 0b00000011, 0b00000000, 0b00000000, ];
282 let command = RemotePortNegotiationParams {
283 dlci: DLCI::try_from(9).unwrap(),
284 port_values: Some(PortValues(port_values_buf)),
285 };
286 let mut buf = vec![0; command.encoded_len()];
287 assert!(command.encode(&mut buf).is_ok());
288
289 let expected = vec![0b00100111]; let expected = [expected, port_values_buf.to_vec()].concat();
291 assert_eq!(buf, expected);
292 }
293}