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