• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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