bt_rfcomm/frame/mux_commands/
non_supported.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;
9
10/// The NonSupportedCommand Response is always 1 byte. See GSM 7.10 Section 5.4.6.3.8.
11const NON_SUPPORTED_COMMAND_RESPONSE_LENGTH: usize = 1;
12
13bitfield! {
14    struct NonSupportedCommandField(u8);
15    impl Debug;
16    pub bool, ea_bit, set_ea_bit: 0;
17    pub bool, cr_bit, set_cr_bit: 1;
18    pub u8, command, set_command: 7, 2;
19}
20
21/// This response is sent whenever a command type is not supported by the device.
22/// Defined in GSM 7.10 Section 5.4.6.3.8.
23#[derive(Clone, Debug, PartialEq)]
24pub struct NonSupportedCommandParams {
25    /// The C/R bit is set to the same value as the C/R bit in the non-supported command.
26    pub cr_bit: bool,
27    /// The non_supported command.
28    pub non_supported_command: u8,
29}
30
31impl Decodable for NonSupportedCommandParams {
32    type Error = FrameParseError;
33
34    fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
35        if buf.len() != NON_SUPPORTED_COMMAND_RESPONSE_LENGTH {
36            return Err(FrameParseError::InvalidBufferLength(
37                NON_SUPPORTED_COMMAND_RESPONSE_LENGTH,
38                buf.len(),
39            ));
40        }
41
42        let command_field = NonSupportedCommandField(buf[0]);
43        let cr_bit = command_field.cr_bit();
44        let non_supported_command = command_field.command();
45
46        Ok(Self { cr_bit, non_supported_command })
47    }
48}
49
50impl Encodable for NonSupportedCommandParams {
51    type Error = FrameParseError;
52
53    fn encoded_len(&self) -> usize {
54        NON_SUPPORTED_COMMAND_RESPONSE_LENGTH
55    }
56
57    fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
58        if buf.len() < self.encoded_len() {
59            return Err(FrameParseError::BufferTooSmall);
60        }
61
62        let mut command_fields = NonSupportedCommandField(0);
63        // The E/A bit is always set for this command (GSM 7.10 Section 5.4.6.3.8.).
64        command_fields.set_ea_bit(true);
65        command_fields.set_cr_bit(self.cr_bit);
66        command_fields.set_command(self.non_supported_command);
67
68        buf[0] = command_fields.0;
69
70        Ok(())
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    use assert_matches::assert_matches;
79
80    #[test]
81    fn test_decode_invalid_buf() {
82        let empty_buf = [];
83        assert_matches!(
84            NonSupportedCommandParams::decode(&empty_buf[..]),
85            Err(FrameParseError::InvalidBufferLength(NON_SUPPORTED_COMMAND_RESPONSE_LENGTH, 0))
86        );
87    }
88
89    #[test]
90    fn test_decode_valid_buf() {
91        let buf = [
92            0b10101011, // C/R Bit = 1, Random Command pattern = 42.
93        ];
94        let expected = NonSupportedCommandParams { cr_bit: true, non_supported_command: 42 };
95        assert_eq!(NonSupportedCommandParams::decode(&buf[..]).unwrap(), expected);
96    }
97
98    #[test]
99    fn test_encode_buffer_too_small() {
100        let mut buf = [];
101        let response = NonSupportedCommandParams { cr_bit: false, non_supported_command: 8 };
102        assert_matches!(response.encode(&mut buf[..]), Err(FrameParseError::BufferTooSmall));
103    }
104
105    #[test]
106    fn test_encode_response() {
107        let mut buf = [0; 1];
108        let response = NonSupportedCommandParams { cr_bit: true, non_supported_command: 8 };
109        let expected = [
110            0b00100011, // Command = 8, C/R = 1, E/A = 1.
111        ];
112        assert!(response.encode(&mut buf[..]).is_ok());
113        assert_eq!(buf, expected);
114    }
115
116    #[test]
117    fn test_encode_command() {
118        let mut buf = [0; 1];
119        let response = NonSupportedCommandParams { cr_bit: false, non_supported_command: 10 };
120        let expected = [
121            0b00101001, // Command = 10, C/R = 0, E/A = 1.
122        ];
123        assert!(response.encode(&mut buf[..]).is_ok());
124        assert_eq!(buf, expected);
125    }
126}