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 std::io::{Error, Read};
16
17 #[derive(Debug)]
18 pub struct Packet {
19 pub h4_type: u8,
20 pub payload: Vec<u8>,
21 }
22
23 #[derive(Debug)]
24 pub enum PacketError {
25 IoError(Error),
26 InvalidPacketType,
27 InvalidPacket,
28 }
29
30 /* H4 message type */
31 const H4_CMD_TYPE: u8 = 1;
32 const H4_ACL_TYPE: u8 = 2;
33 const H4_SCO_TYPE: u8 = 3;
34 const H4_EVT_TYPE: u8 = 4;
35 const H4_ISO_TYPE: u8 = 5;
36
37 /* HCI message preamble size */
38 const HCI_CMD_PREAMBLE_SIZE: usize = 3;
39 const HCI_ACL_PREAMBLE_SIZE: usize = 4;
40 const HCI_SCO_PREAMBLE_SIZE: usize = 3;
41 const HCI_EVT_PREAMBLE_SIZE: usize = 2;
42 const HCI_ISO_PREAMBLE_SIZE: usize = 4;
43
44 // TODO: recovery mode to get back on sync
read_h4_packet<R: Read>(reader: &mut R) -> Result<Packet, PacketError>45 pub fn read_h4_packet<R: Read>(reader: &mut R) -> Result<Packet, PacketError> {
46 // Read the h4 type and obtain the preamble length
47 let mut buffer = [0u8; 1];
48 reader.read_exact(&mut buffer).map_err(PacketError::IoError)?;
49 let h4_type = buffer[0];
50 let preamble_size = match h4_type {
51 H4_CMD_TYPE => HCI_CMD_PREAMBLE_SIZE,
52 H4_ACL_TYPE => HCI_ACL_PREAMBLE_SIZE,
53 H4_SCO_TYPE => HCI_SCO_PREAMBLE_SIZE,
54 H4_EVT_TYPE => HCI_EVT_PREAMBLE_SIZE,
55 H4_ISO_TYPE => HCI_ISO_PREAMBLE_SIZE,
56 _ => return Err(PacketError::InvalidPacketType),
57 };
58
59 // Read the preamble and obtain the payload length
60 let mut packet = vec![0u8; preamble_size];
61 reader.read_exact(&mut packet).map_err(PacketError::IoError)?;
62 let payload_length: usize = match h4_type {
63 H4_CMD_TYPE => {
64 // Command: 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
65 packet[2] as usize
66 }
67 H4_ACL_TYPE => {
68 // ACL: 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
69 u16::from_le_bytes([packet[2], packet[3]]) as usize
70 }
71 H4_SCO_TYPE => {
72 // SCO: 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
73 packet[2] as usize
74 }
75 H4_EVT_TYPE => {
76 // Event: 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
77 packet[1] as usize
78 }
79 H4_ISO_TYPE => {
80 // 2 bytes for handle and flags, 12 bits for length (Volume 2, Part E, 5.4.5)
81 usize::from(packet[3] & 0x0f) << 8 | usize::from(packet[2])
82 }
83 _ => panic!("Unknown H4 packet type."),
84 };
85 // Read and append the payload and return
86 packet.resize(preamble_size + payload_length, 0u8);
87 reader.read_exact(&mut packet[preamble_size..]).map_err(PacketError::IoError)?;
88 Ok(Packet { h4_type, payload: packet })
89 }
90
91 #[cfg(test)]
92 mod tests {
93 use super::read_h4_packet;
94 use super::H4_ACL_TYPE;
95 use std::io::Cursor;
96
97 #[test]
test_acl()98 fn test_acl() {
99 let hci_acl: Vec<u8> = vec![
100 0x02, 0x2a, 0x20, 0x11, 0x00, 0x15, 0x00, 0x40, 0x00, 0x06, 0x00, 0x01, 0x00, 0x10,
101 0x36, 0x00, 0x03, 0x19, 0x11, 0x08, 0x02, 0xa0,
102 ];
103 let mut file = Cursor::new(hci_acl);
104 let response = read_h4_packet(&mut file);
105 assert!(&response.is_ok());
106 assert_eq!(response.as_ref().unwrap().h4_type, H4_ACL_TYPE);
107 assert_eq!(response.as_ref().unwrap().payload.len(), 21);
108 }
109 }
110