bt_rfcomm/frame/mux_commands/
modem_status.rs
1use bitfield::bitfield;
6use packet_encoding::{Decodable, Encodable};
7
8use crate::frame::FrameParseError;
9use crate::DLCI;
10
11const MODEM_STATUS_COMMAND_WITHOUT_BREAK_LENGTH: usize = 2;
13
14const MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH: usize = 3;
16
17bitfield! {
18 struct ModemStatusAddressField(u8);
20 impl Debug;
21 bool;
22 pub ea_bit, set_ea_bit: 0;
23 pub cr_bit, set_cr_bit: 1;
24 pub u8, dlci_raw, set_dlci: 7,2;
25}
26
27impl ModemStatusAddressField {
28 fn dlci(&self) -> Result<DLCI, FrameParseError> {
29 DLCI::try_from(self.dlci_raw())
30 }
31}
32
33bitfield! {
34 pub struct ModemStatusSignals(u8);
36 impl Debug;
37 bool;
38 pub ea_bit, set_ea_bit: 0;
39 pub flow_control, set_flow_control: 1;
40 pub ready_to_communicate, set_ready_to_communicate: 2;
41 pub ready_to_receive, set_ready_to_receive: 3;
42 pub incoming_call, set_incoming_call: 6;
43 pub data_valid, set_data_valid: 7;
44}
45
46impl Clone for ModemStatusSignals {
47 fn clone(&self) -> Self {
48 Self(self.0)
49 }
50}
51
52impl Default for ModemStatusSignals {
53 fn default() -> Self {
57 let mut signals = Self(0);
58 signals.set_ea_bit(true); signals.set_flow_control(false); signals.set_ready_to_communicate(true); signals.set_ready_to_receive(true); signals.set_incoming_call(false); signals.set_data_valid(true); signals
65 }
66}
67
68bitfield! {
69 struct ModemStatusBreakField(u8);
71 impl Debug;
72 bool;
73 pub ea_bit, set_ea_bit: 0;
74 pub contains_break_value, set_contains_break_value: 1;
75 pub u8, break_value, set_break_value: 7,4;
76}
77
78impl PartialEq for ModemStatusSignals {
79 fn eq(&self, other: &Self) -> bool {
80 self.0 == other.0
81 }
82}
83
84#[derive(Clone, Debug, PartialEq)]
87pub struct ModemStatusParams {
88 pub dlci: DLCI,
89 pub signals: ModemStatusSignals,
90 pub break_value: Option<u8>,
92}
93
94impl ModemStatusParams {
95 pub fn default(dlci: DLCI) -> Self {
97 Self { dlci, signals: ModemStatusSignals::default(), break_value: None }
98 }
99}
100
101impl Decodable for ModemStatusParams {
102 type Error = FrameParseError;
103
104 fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
105 if buf.len() != MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH
106 && buf.len() != MODEM_STATUS_COMMAND_WITHOUT_BREAK_LENGTH
107 {
108 return Err(FrameParseError::InvalidBufferLength(
109 MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH,
110 buf.len(),
111 ));
112 }
113
114 let address_field = ModemStatusAddressField(buf[0]);
116 let dlci = address_field.dlci()?;
117
118 let signals = ModemStatusSignals(buf[1]);
120
121 let mut break_value = None;
123 if buf.len() == MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH {
124 let value = ModemStatusBreakField(buf[2]);
125 if value.contains_break_value() {
126 break_value = Some(value.break_value());
127 }
128 }
129
130 Ok(Self { dlci, signals, break_value })
131 }
132}
133
134impl Encodable for ModemStatusParams {
135 type Error = FrameParseError;
136
137 fn encoded_len(&self) -> usize {
138 if self.break_value.is_some() {
139 MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH
140 } else {
141 MODEM_STATUS_COMMAND_WITHOUT_BREAK_LENGTH
142 }
143 }
144
145 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
146 if buf.len() < self.encoded_len() {
147 return Err(FrameParseError::BufferTooSmall);
148 }
149
150 let mut address_field = ModemStatusAddressField(0);
152 address_field.set_ea_bit(true);
153 address_field.set_cr_bit(true);
154 address_field.set_dlci(u8::from(self.dlci));
155 buf[0] = address_field.0;
156
157 let mut status_signals_field = ModemStatusSignals(self.signals.0);
159 let ea_bit = self.break_value.is_none();
160 status_signals_field.set_ea_bit(ea_bit);
161 buf[1] = status_signals_field.0;
162
163 if self.break_value.is_some() {
165 let mut break_value_field = ModemStatusBreakField(0);
166 break_value_field.set_ea_bit(true);
167 break_value_field.set_contains_break_value(true);
168 break_value_field.set_break_value(self.break_value.unwrap());
169 buf[2] = break_value_field.0;
170 }
171
172 Ok(())
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 use assert_matches::assert_matches;
181
182 #[test]
183 fn test_decode_modem_status_invalid_buf() {
184 let buf = [];
185 assert_matches!(
186 ModemStatusParams::decode(&buf[..]),
187 Err(FrameParseError::InvalidBufferLength(MODEM_STATUS_COMMAND_WITH_BREAK_LENGTH, 0))
188 );
189 }
190
191 #[test]
192 fn test_decode_modem_status_invalid_dlci() {
193 let buf = [
194 0b00000111, 0b00000001, ];
197 assert_matches!(ModemStatusParams::decode(&buf[..]), Err(FrameParseError::InvalidDLCI(1)));
198 }
199
200 #[test]
201 fn test_decode_modem_status_without_break_value() {
202 let buf = [
203 0b00001111, 0b00000001, ];
206 let expected = ModemStatusParams {
207 dlci: DLCI::try_from(3).unwrap(),
208 signals: ModemStatusSignals(1),
209 break_value: None,
210 };
211 assert_eq!(ModemStatusParams::decode(&buf[..]).unwrap(), expected);
212 }
213
214 #[test]
215 fn test_decode_modem_status_with_empty_break_value() {
216 let buf = [
217 0b00001111, 0b00000000, 0b00000001, ];
221 let expected = ModemStatusParams {
222 dlci: DLCI::try_from(3).unwrap(),
223 signals: ModemStatusSignals(0),
224 break_value: None,
225 };
226 assert_eq!(ModemStatusParams::decode(&buf[..]).unwrap(), expected);
227 }
228
229 #[test]
230 fn test_decode_modem_status_with_break_value() {
231 let buf = [
232 0b00011111, 0b11000011, 0b10100011, ];
236 let expected = ModemStatusParams {
237 dlci: DLCI::try_from(7).unwrap(),
238 signals: ModemStatusSignals(195),
239 break_value: Some(10),
240 };
241 assert_eq!(ModemStatusParams::decode(&buf[..]).unwrap(), expected);
242 }
243
244 #[test]
245 fn test_encode_modem_status_invalid_buf() {
246 let mut buf = [];
247 let command = ModemStatusParams {
248 dlci: DLCI::try_from(5).unwrap(),
249 signals: ModemStatusSignals(100),
250 break_value: Some(11),
251 };
252 assert_matches!(command.encode(&mut buf[..]), Err(FrameParseError::BufferTooSmall));
253 }
254
255 #[test]
256 fn test_encode_modem_status_no_break_signal() {
257 let mut buf = [0; 2];
258 let command = ModemStatusParams {
259 dlci: DLCI::try_from(5).unwrap(),
260 signals: ModemStatusSignals(1),
261 break_value: None,
262 };
263 let expected = [
264 0b00010111, 0b00000001, ];
267 assert!(command.encode(&mut buf[..]).is_ok());
268 assert_eq!(buf, expected);
269 }
270
271 #[test]
272 fn test_encode_modem_status_with_break_signal() {
273 let mut buf = [0; 3];
274 let command = ModemStatusParams {
275 dlci: DLCI::try_from(6).unwrap(),
276 signals: ModemStatusSignals(201),
277 break_value: Some(3),
278 };
279 let expected = [
280 0b00011011, 0b11001000, 0b00110011, ];
284 assert!(command.encode(&mut buf[..]).is_ok());
285 assert_eq!(buf, expected);
286 }
287}