bt_rfcomm/frame/mux_commands/
remote_port_negotiation.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bitfield::bitfield;
6use packet_encoding::{Decodable, Encodable};
7
8use crate::frame::FrameParseError;
9use crate::DLCI;
10
11/// The length (in bytes) of a "short" RPN command - contains only 1 octet for the DLCI.
12/// A short RPN command is used to request the remote port settings.
13const REMOTE_PORT_NEGOTIATION_SHORT_LENGTH: usize = 1;
14
15/// The length (in bytes) of a "long" RPN command containing 1 octet for the DLCI
16/// and 7 octets for the parameter values.
17/// A long RPN command is used to negotiate the remote port settings.
18const REMOTE_PORT_NEGOTIATION_LONG_LENGTH: usize = 8;
19
20/// The length (in bytes) of the values associated with an RPN command.
21/// Defined in GSM 7.10 Section 5.4.6.3.9 Table 11.
22const 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
38/// The PortValues mask indicating a unanimous accepting of all negotiated
39/// port values.
40/// Bit 8 is reserved. Bits 15,16 are unused. All unused/reserved bits are set to 0.
41/// Defined in GSM 7.10 Section 5.4.6.3.9.
42const 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    /// Returns the default values for the PortValues.
72    ///
73    /// The `parity` and `mask` fields do not have defaults in the spec and are set to 0.
74    /// See GSM 7.10 Section 5.4.6.3.9 below Table 12 for the default values.
75    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); // No default defined.
82        values.set_flow_control(0x00);
83        values.set_xon_character(0x01);
84        values.set_xoff_character(0x03);
85        values.set_mask(0x00); // No default defined.
86        values
87    }
88}
89
90/// The Remote Port Negotiation (RPN) command is used whenever the port settings change.
91/// Defined in GSM 7.10 Section 5.4.6.3.9, with RFCOMM notes in RFCOMM 5.5.1.
92#[derive(Clone, Debug, PartialEq)]
93pub struct RemotePortNegotiationParams {
94    pub dlci: DLCI,
95    /// The optional port values to be used when negotiation the parameters.
96    pub port_values: Option<PortValues<[u8; REMOTE_PORT_NEGOTIATION_VALUES_LENGTH]>>,
97}
98
99impl RemotePortNegotiationParams {
100    /// Returns the appropriate response for the RPN Command.
101    ///
102    /// If there are no port_values, then the command is a request for the current port_values.
103    /// Returns the default values specified in GSM 7.10 Section 5.4.6.3.9.
104    /// Otherwise, it's a negotiation request for port values. Returns the negotiated
105    /// port values.
106    pub fn response(&self) -> Self {
107        let port_values =
108            self.port_values.clone().map_or_else(PortValues::default, |mut values| {
109                // This implementation unanimously accepts the port values given by
110                // the remote peer.
111                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        // Address field.
132        let address_field = RpnAddressField(buf[0]);
133        let dlci = address_field.dlci()?;
134
135        // Port Values field.
136        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        // E/A bit = 1, C/R bit = 1. See GSM 7.10 Section 5.4.6.3.9 Table 10.
165        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]; // Length = 3, invalid.
188        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, // DLCI = 1 is invalid, E/A = 1, Bit2 = 1 always.
198        ];
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, // DLCI = 7 is OK, E/A = 1, Bit2 = 1 always.
209        ];
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, // Octet 1: Baud Rate = 1.
219            0b00101011, // Octet 2: Data Bits = 0b11, Stop = false, Parity = true, Type = 0b10.
220            0b00011010, // Octet 3: Flow Control = 26.
221            0b00000001, // Octet 4: XOn = 1.
222            0b00000011, // Octet 5: XOff = 3.
223            0b10000001, // Octet 6: Mask = 385 (Octet1 = 129).
224            0b00000001, // Octet 7: Mask = 385 (Octet2 = 256).
225        ];
226        let buf = vec![
227            0b00011111, // DLCI = 7 is OK, E/A = 1, Bit2 = 1 always.
228        ];
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]; // DLCI = 2.
267        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, // Octet 1: Baud Rate = 16.
275            0b00111100, // Octet 2: Data Bits = 0b00, Stop = true, Parity = true, Type = 0b11.
276            0b00000010, // Octet 3: Flow Control = 2.
277            0b00000001, // Octet 4: XOn = 1.
278            0b00000011, // Octet 5: XOff = 3.
279            0b00000000, // Octet 6: Mask = 0 (Octet1 = 0).
280            0b00000000, // Octet 7: Mask = 0 (Octet2 = 0).
281        ];
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]; // DLCI = 9.
290        let expected = [expected, port_values_buf.to_vec()].concat();
291        assert_eq!(buf, expected);
292    }
293}