xref: /aosp_15_r20/tools/netsim/rust/daemon/src/transport/h4.rs (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use bytes::Bytes;
16 use log::{error, warn};
17 use std::collections::VecDeque;
18 use std::io::{Error, Read};
19 
20 #[derive(Debug)]
21 pub struct Packet {
22     pub h4_type: u8,
23     pub payload: Bytes,
24 }
25 
26 #[derive(Debug)]
27 pub enum PacketError {
28     IoError(Error),
29     #[allow(dead_code)]
30     InvalidPacketType,
31     #[allow(dead_code)]
32     InvalidPacket,
33 }
34 
35 /* H4 message type */
36 const H4_CMD_TYPE: u8 = 1;
37 const H4_ACL_TYPE: u8 = 2;
38 const H4_SCO_TYPE: u8 = 3;
39 const H4_EVT_TYPE: u8 = 4;
40 const H4_ISO_TYPE: u8 = 5;
41 
42 /* HCI message preamble size */
43 const HCI_CMD_PREAMBLE_SIZE: usize = 3;
44 const HCI_ACL_PREAMBLE_SIZE: usize = 4;
45 const HCI_SCO_PREAMBLE_SIZE: usize = 3;
46 const HCI_EVT_PREAMBLE_SIZE: usize = 2;
47 const HCI_ISO_PREAMBLE_SIZE: usize = 4;
48 
49 /// Read and return the h4 packet.
read_h4_packet<R: Read>(reader: &mut R) -> Result<Packet, PacketError>50 pub fn read_h4_packet<R: Read>(reader: &mut R) -> Result<Packet, PacketError> {
51     // Read the h4 type and obtain the preamble length
52     let mut buffer = [0u8; 1];
53     reader.read_exact(&mut buffer).map_err(PacketError::IoError)?;
54     let h4_type = buffer[0];
55     let preamble_size = match h4_type {
56         H4_CMD_TYPE => HCI_CMD_PREAMBLE_SIZE,
57         H4_ACL_TYPE => HCI_ACL_PREAMBLE_SIZE,
58         H4_SCO_TYPE => HCI_SCO_PREAMBLE_SIZE,
59         H4_EVT_TYPE => HCI_EVT_PREAMBLE_SIZE,
60         H4_ISO_TYPE => HCI_ISO_PREAMBLE_SIZE,
61         _ => return h4_recovery(reader),
62     };
63 
64     // Read the preamble and obtain the payload length
65     let mut packet = vec![0u8; preamble_size];
66     reader.read_exact(&mut packet).map_err(PacketError::IoError)?;
67     let payload_length: usize = match h4_type {
68         H4_CMD_TYPE => {
69             // Command: 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
70             packet[2] as usize
71         }
72         H4_ACL_TYPE => {
73             // ACL: 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
74             u16::from_le_bytes([packet[2], packet[3]]) as usize
75         }
76         H4_SCO_TYPE => {
77             // SCO: 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
78             packet[2] as usize
79         }
80         H4_EVT_TYPE => {
81             // Event: 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
82             packet[1] as usize
83         }
84         H4_ISO_TYPE => {
85             // 2 bytes for handle and flags, 12 bits for length (Volume 2, Part E, 5.4.5)
86             usize::from(packet[3] & 0x0f) << 8 | usize::from(packet[2])
87         }
88         _ => {
89             // This case was handled above resulting in call to h4_recovery
90             panic!("Unknown H4 packet type")
91         }
92     };
93     // Read and append the payload and return
94     packet.resize(preamble_size + payload_length, 0u8);
95     let result = reader.read_exact(&mut packet[preamble_size..]);
96     if let Err(e) = result {
97         error!(
98             "h4 failed to read {payload_length} bytes for type: {h4_type} preamble: {:?} error: {e}",
99             &packet[0..preamble_size]
100         );
101         return Err(PacketError::IoError(e));
102     }
103     Ok(Packet { h4_type, payload: Bytes::from(packet) })
104 }
105 
106 /// Skip all received bytes until the HCI Reset command is received.
107 ///
108 /// Cuttlefish sometimes sends invalid bytes in the virtio-console to
109 /// rootcanal/netsim when the emulator is restarted in the middle of
110 /// HCI exchanges. This function recovers from this situation: when an
111 /// invalid IDC is received all incoming bytes are dropped until the
112 /// HCI RESET command is recognized in the input stream
113 ///
114 /// Based on packages/modules/Bluetooth/tools/rootcanal/model/hci/h4_parser.cc
115 ///
h4_recovery<R: Read>(mut reader: R) -> Result<Packet, PacketError>116 fn h4_recovery<R: Read>(mut reader: R) -> Result<Packet, PacketError> {
117     const RESET_COMMAND: [u8; 4] = [0x01, 0x03, 0x0c, 0x00];
118     let reset_pattern = VecDeque::from(RESET_COMMAND.to_vec());
119     let mut buffer = VecDeque::with_capacity(reset_pattern.len());
120 
121     warn!("Entering h4 recovery state...");
122 
123     let mut byte = [0; 1];
124     loop {
125         reader.read_exact(&mut byte).map_err(PacketError::IoError)?;
126         // bufer contains a sliding window of reset_pattern.len()
127         // across the input bytes.
128         if buffer.len() == reset_pattern.len() {
129             buffer.pop_front();
130         }
131 
132         buffer.push_back(byte[0]);
133         if buffer == reset_pattern {
134             warn!("Received HCI Reset command, exiting recovery state");
135             return Ok(Packet {
136                 h4_type: RESET_COMMAND[0],
137                 payload: Bytes::from(RESET_COMMAND[1..].to_vec()),
138             });
139         }
140     }
141 }
142 
143 #[cfg(test)]
144 mod tests {
145     use super::PacketError;
146     use super::{h4_recovery, read_h4_packet};
147     use super::{H4_ACL_TYPE, H4_CMD_TYPE, H4_EVT_TYPE, H4_ISO_TYPE, H4_SCO_TYPE};
148     use std::io::{BufReader, Cursor};
149 
150     // Validate packet types
151 
152     #[test]
test_read_h4_cmd_packet()153     fn test_read_h4_cmd_packet() {
154         let hci_cmd = vec![0x01, 0x03, 0x0c, 0x00];
155         let mut reader = Cursor::new(&hci_cmd);
156         let packet = read_h4_packet(&mut reader).unwrap();
157         assert_eq!(packet.h4_type, H4_CMD_TYPE);
158         assert_eq!(packet.payload, hci_cmd[1..]);
159     }
160 
161     #[test]
test_read_h4_acl_packet()162     fn test_read_h4_acl_packet() {
163         let hci_acl = vec![
164             0x02, 0x2a, 0x20, 0x11, 0x00, 0x15, 0x00, 0x40, 0x00, 0x06, 0x00, 0x01, 0x00, 0x10,
165             0x36, 0x00, 0x03, 0x19, 0x11, 0x08, 0x02, 0xa0,
166         ];
167         let mut reader = Cursor::new(&hci_acl);
168         let packet = read_h4_packet(&mut reader).unwrap();
169         assert_eq!(packet.h4_type, H4_ACL_TYPE);
170         assert_eq!(packet.payload, hci_acl[1..]);
171     }
172 
173     #[test]
test_read_h4_sco_packet()174     fn test_read_h4_sco_packet() {
175         let hci_sco = vec![0x03, 0x03, 0x0c, 0x02, 0x01, 0x02];
176         let mut reader = Cursor::new(&hci_sco);
177         let packet = read_h4_packet(&mut reader).unwrap();
178         assert_eq!(packet.h4_type, H4_SCO_TYPE);
179         assert_eq!(packet.payload, hci_sco[1..]);
180     }
181 
182     #[test]
test_read_h4_evt_packet()183     fn test_read_h4_evt_packet() {
184         let hci_evt = vec![0x04, 0x0C, 0x01, 0x10];
185         let mut reader = Cursor::new(&hci_evt);
186         let packet = read_h4_packet(&mut reader).unwrap();
187         assert_eq!(packet.h4_type, H4_EVT_TYPE);
188         assert_eq!(packet.payload, hci_evt[1..]);
189     }
190 
191     #[test]
test_read_h4_iso_packet()192     fn test_read_h4_iso_packet() {
193         let hci_iso = vec![0x05, 0x02, 0x00, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
194         let mut reader = Cursor::new(&hci_iso);
195         let packet = read_h4_packet(&mut reader).unwrap();
196         assert_eq!(packet.h4_type, H4_ISO_TYPE);
197         assert_eq!(packet.payload, hci_iso[1..]);
198     }
199 
200     // Test invalid packet length
201 
202     #[test]
test_read_h4_packet_with_eof_in_type()203     fn test_read_h4_packet_with_eof_in_type() {
204         let hci_acl: Vec<u8> = vec![];
205         let mut file = Cursor::new(hci_acl);
206         let result = read_h4_packet(&mut file);
207         assert!(result.is_err());
208         matches!(result.unwrap_err(), PacketError::InvalidPacketType);
209     }
210 
211     #[test]
test_read_h4_packet_with_eof_in_preamble()212     fn test_read_h4_packet_with_eof_in_preamble() {
213         let mut reader = Cursor::new(&[0x01, 0x03, 0x0c]);
214         let result = read_h4_packet(&mut reader);
215         assert!(result.is_err());
216         matches!(result.unwrap_err(), PacketError::InvalidPacketType);
217     }
218 
219     #[test]
test_read_h4_packet_with_eof_in_payload()220     fn test_read_h4_packet_with_eof_in_payload() {
221         let mut reader = Cursor::new(&[0x01, 0x03, 0x0c, 0x01]);
222         let result = read_h4_packet(&mut reader);
223         assert!(result.is_err());
224         matches!(result.unwrap_err(), PacketError::InvalidPacketType);
225     }
226 
227     // Test h4_recovery
228 
229     #[test]
test_h4_recovery_with_reset_first()230     fn test_h4_recovery_with_reset_first() {
231         let input = b"\0x08\x01\x03\x0c\x00";
232         let mut reader = BufReader::new(&input[..]);
233         let packet = h4_recovery(&mut reader).unwrap();
234         assert_eq!(packet.h4_type, 0x01);
235         assert_eq!(packet.payload, vec![0x03, 0x0c, 0x00]);
236     }
237 
238     #[test]
test_h4_recovery_with_reset_after_many()239     fn test_h4_recovery_with_reset_after_many() {
240         let input = b"randombytes\x01\x03\x0c\x00";
241         let mut reader = BufReader::new(&input[..]);
242         let packet = h4_recovery(&mut reader).unwrap();
243         assert_eq!(packet.h4_type, 0x01);
244         assert_eq!(packet.payload, vec![0x03, 0x0c, 0x00]);
245     }
246 
247     #[test]
test_h4_recovery_with_eof()248     fn test_h4_recovery_with_eof() {
249         let input = b"\0x08\x01\x03\x0c";
250         let reader = BufReader::new(&input[..]);
251         let result = h4_recovery(reader);
252         assert!(result.is_err());
253         matches!(result.unwrap_err(), PacketError::IoError(_));
254     }
255 }
256