summaryrefslogtreecommitdiff
path: root/floss
diff options
context:
space:
mode:
author Archie Pusaka <apusaka@chromium.org> 2024-10-22 17:30:46 +0800
committer Archie Pusaka <apusaka@google.com> 2024-10-23 19:04:04 +0800
commitb309d99f3f08dd94d0874a2ab00dd9b5dffab453 (patch)
treed5b870168936a18827efe203d758d2e5865f1f51 /floss
parentd86585a62f65cd989a9465d1522a7a18139196d2 (diff)
Hcidoc: Use hci_packets.pdl in rootcanal
The hci_packets.pdl in system/pdl doesn't seem to be fully compatible with the pdl-compiler. Therefore, use the one in rootcanal instead. Since they have different structure, some adjustments needs to be made. In particular, this one doesn't have nested HCI structure, and doesn't have GAP Data implementation. Bug: 289858128 Test: m -j Test: Manual verification Flag: EXEMPT, floss only changes Change-Id: I0ede46f80cc0e371bc69ccdbd9f2b60e9be6ccd8
Diffstat (limited to 'floss')
-rw-r--r--floss/hcidoc/packets/build.rs2
-rw-r--r--floss/hcidoc/packets/lib.rs42
-rw-r--r--floss/hcidoc/src/groups/connections.rs232
-rw-r--r--floss/hcidoc/src/groups/informational.rs86
4 files changed, 175 insertions, 187 deletions
diff --git a/floss/hcidoc/packets/build.rs b/floss/hcidoc/packets/build.rs
index 7a08060feb..f9d0304a55 100644
--- a/floss/hcidoc/packets/build.rs
+++ b/floss/hcidoc/packets/build.rs
@@ -44,7 +44,7 @@ fn generate_packets() {
);
let out_file = File::create(out_dir.join("hci_packets.rs")).unwrap();
- let in_file = PathBuf::from("../../../system/pdl/hci/hci_packets.pdl");
+ let in_file = PathBuf::from("../../../tools/rootcanal/packets/hci_packets.pdl");
println!("cargo:rerun-if-changed={}", in_file.display());
let output = Command::new("pdlc")
diff --git a/floss/hcidoc/packets/lib.rs b/floss/hcidoc/packets/lib.rs
index af9d810145..4a71e58e13 100644
--- a/floss/hcidoc/packets/lib.rs
+++ b/floss/hcidoc/packets/lib.rs
@@ -36,4 +36,46 @@ pub mod hci {
bytes[0..6].try_into().unwrap()
}
}
+
+ pub struct GapData {
+ pub data_type: GapDataType,
+ pub data: Vec<u8>,
+ }
+
+ impl GapData {
+ pub fn parse(bytes: &[u8]) -> std::result::Result<Self, String> {
+ // In case of parsing EIR, we can get normal data, or all zeroes. Normal data always
+ // have at least 2 bytes: one for the length, and another for the type. Therefore we
+ // can terminate early if the data has less than 2 bytes.
+ if (bytes.len() == 0) {
+ return Err("no data to parse".to_string());
+ } else if (bytes.len() == 1) {
+ if (bytes[0] != 0) {
+ return Err(format!("can't parse 1 byte of data: {}", bytes[0]));
+ }
+ return Ok(GapData { data_type: GapDataType::Invalid, data: vec![] });
+ }
+
+ let mut data_size = bytes[0] as usize;
+ if (data_size == 0) {
+ // Data size already include the data_type, so size = 0 is possible only when
+ // parsing EIR, where all data are zeroes. Here we just assume that assumption is
+ // correct, and don't really check all the elements.
+ return Ok(GapData { data_type: GapDataType::Invalid, data: bytes[2..].to_vec() });
+ }
+
+ if (data_size > bytes.len() - 1) {
+ return Err(format!(
+ "size {} is bigger than remaining length {}",
+ data_size,
+ bytes.len() - 1
+ ));
+ }
+ let data_type = match GapDataType::try_from(bytes[1]) {
+ Ok(data_type) => Ok(data_type),
+ Err(_) => Err(format!("can't parse data type {}", bytes[1])),
+ }?;
+ return Ok(GapData { data_type, data: bytes[2..(data_size + 1)].to_vec() });
+ }
+ }
}
diff --git a/floss/hcidoc/src/groups/connections.rs b/floss/hcidoc/src/groups/connections.rs
index 9c1526f1b7..0f22e73e5f 100644
--- a/floss/hcidoc/src/groups/connections.rs
+++ b/floss/hcidoc/src/groups/connections.rs
@@ -8,11 +8,9 @@ use std::slice::Iter;
use crate::engine::{Rule, RuleGroup, Signal};
use crate::parser::{Packet, PacketChild};
use hcidoc_packets::hci::{
- Acl, AclCommandChild, Address, AuthenticatedPayloadTimeoutExpired, CommandChild,
- ConnectionManagementCommandChild, DisconnectReason, Enable, ErrorCode, EventChild,
- InitiatorFilterPolicy, LeConnectionManagementCommandChild, LeMetaEventChild,
- LeSecurityCommandChild, NumberOfCompletedPackets, OpCode, ScoConnectionCommandChild,
- SecurityCommandChild,
+ Acl, Address, AuthenticatedPayloadTimeoutExpired, CommandChild, DisconnectReason, Enable,
+ ErrorCode, EventChild, InitiatorFilterPolicy, LeMetaEventChild, NumberOfCompletedPackets,
+ OpCode,
};
enum ConnectionSignal {
@@ -626,100 +624,77 @@ impl Rule for OddDisconnectionsRule {
fn process(&mut self, packet: &Packet) {
match &packet.inner {
PacketChild::HciCommand(cmd) => match cmd.specialize() {
- CommandChild::AclCommand(aclpkt) => match aclpkt.specialize() {
- AclCommandChild::ConnectionManagementCommand(conn) => match conn.specialize() {
- ConnectionManagementCommandChild::CreateConnection(cc) => {
- self.process_classic_connection(cc.get_bd_addr(), packet);
- }
- ConnectionManagementCommandChild::AcceptConnectionRequest(ac) => {
- self.process_classic_connection(ac.get_bd_addr(), packet);
- }
- ConnectionManagementCommandChild::ReadRemoteSupportedFeatures(rrsf) => {
- self.process_remote_feat_cmd(
- PendingRemoteFeature::Supported,
- &rrsf.get_connection_handle(),
- packet,
- );
- }
- ConnectionManagementCommandChild::ReadRemoteExtendedFeatures(rref) => {
- self.process_remote_feat_cmd(
- PendingRemoteFeature::Extended,
- &rref.get_connection_handle(),
- packet,
- );
- }
- // End ConnectionManagementCommand.specialize()
- _ => {}
- },
- AclCommandChild::ScoConnectionCommand(sco_con) => match sco_con.specialize() {
- ScoConnectionCommandChild::SetupSynchronousConnection(ssc) => {
- let address =
- self.convert_sco_handle_to_address(ssc.get_connection_handle());
- self.process_sync_connection(address, packet);
- }
- ScoConnectionCommandChild::EnhancedSetupSynchronousConnection(esc) => {
- let address =
- self.convert_sco_handle_to_address(esc.get_connection_handle());
- self.process_sync_connection(address, packet);
- }
- ScoConnectionCommandChild::AcceptSynchronousConnection(asc) => {
- self.process_sync_connection(asc.get_bd_addr(), packet);
- }
- ScoConnectionCommandChild::EnhancedAcceptSynchronousConnection(easc) => {
- self.process_sync_connection(easc.get_bd_addr(), packet);
- }
- // End ScoConnectionCommand.specialize()
- _ => {}
- },
- AclCommandChild::LeConnectionManagementCommand(le_conn) => match le_conn
- .specialize()
- {
- LeConnectionManagementCommandChild::LeCreateConnection(lcc) => {
- self.process_le_create_connection(
- lcc.get_peer_address(),
- lcc.get_initiator_filter_policy(),
- packet,
- );
- }
- LeConnectionManagementCommandChild::LeExtendedCreateConnection(lecc) => {
- self.process_le_create_connection(
- lecc.get_peer_address(),
- lecc.get_initiator_filter_policy(),
- packet,
- );
- }
- LeConnectionManagementCommandChild::LeAddDeviceToFilterAcceptList(laac) => {
- self.process_add_accept_list(laac.get_address(), packet);
- }
- LeConnectionManagementCommandChild::LeRemoveDeviceFromFilterAcceptList(
- lrac,
- ) => {
- self.process_remove_accept_list(lrac.get_address(), packet);
- }
- LeConnectionManagementCommandChild::LeClearFilterAcceptList(_lcac) => {
- self.process_clear_accept_list(packet);
- }
- LeConnectionManagementCommandChild::LeReadRemoteFeatures(lrrf) => {
- self.process_remote_feat_cmd(
- PendingRemoteFeature::Le,
- &lrrf.get_connection_handle(),
- packet,
- );
- }
- // End LeConnectionManagementCommand.specialize()
- _ => {}
- },
- AclCommandChild::Disconnect(dc_conn) => {
- self.process_disconnect_cmd(
- dc_conn.get_reason(),
- dc_conn.get_connection_handle(),
- packet,
- );
- }
-
- // End AclCommand.specialize()
- _ => (),
- },
+ CommandChild::CreateConnection(cc) => {
+ self.process_classic_connection(cc.get_bd_addr(), packet);
+ }
+ CommandChild::AcceptConnectionRequest(ac) => {
+ self.process_classic_connection(ac.get_bd_addr(), packet);
+ }
+ CommandChild::ReadRemoteSupportedFeatures(rrsf) => {
+ self.process_remote_feat_cmd(
+ PendingRemoteFeature::Supported,
+ &rrsf.get_connection_handle(),
+ packet,
+ );
+ }
+ CommandChild::ReadRemoteExtendedFeatures(rref) => {
+ self.process_remote_feat_cmd(
+ PendingRemoteFeature::Extended,
+ &rref.get_connection_handle(),
+ packet,
+ );
+ }
+ CommandChild::SetupSynchronousConnection(ssc) => {
+ let address = self.convert_sco_handle_to_address(ssc.get_connection_handle());
+ self.process_sync_connection(address, packet);
+ }
+ CommandChild::EnhancedSetupSynchronousConnection(esc) => {
+ let address = self.convert_sco_handle_to_address(esc.get_connection_handle());
+ self.process_sync_connection(address, packet);
+ }
+ CommandChild::AcceptSynchronousConnection(asc) => {
+ self.process_sync_connection(asc.get_bd_addr(), packet);
+ }
+ CommandChild::EnhancedAcceptSynchronousConnection(easc) => {
+ self.process_sync_connection(easc.get_bd_addr(), packet);
+ }
+ CommandChild::LeCreateConnection(lcc) => {
+ self.process_le_create_connection(
+ lcc.get_peer_address(),
+ lcc.get_initiator_filter_policy(),
+ packet,
+ );
+ }
+ CommandChild::LeExtendedCreateConnection(lecc) => {
+ self.process_le_create_connection(
+ lecc.get_peer_address(),
+ lecc.get_initiator_filter_policy(),
+ packet,
+ );
+ }
+ CommandChild::LeAddDeviceToFilterAcceptList(laac) => {
+ self.process_add_accept_list(laac.get_address(), packet);
+ }
+ CommandChild::LeRemoveDeviceFromFilterAcceptList(lrac) => {
+ self.process_remove_accept_list(lrac.get_address(), packet);
+ }
+ CommandChild::LeClearFilterAcceptList(_lcac) => {
+ self.process_clear_accept_list(packet);
+ }
+ CommandChild::LeReadRemoteFeatures(lrrf) => {
+ self.process_remote_feat_cmd(
+ PendingRemoteFeature::Le,
+ &lrrf.get_connection_handle(),
+ packet,
+ );
+ }
+ CommandChild::Disconnect(dc_conn) => {
+ self.process_disconnect_cmd(
+ dc_conn.get_reason(),
+ dc_conn.get_connection_handle(),
+ packet,
+ );
+ }
CommandChild::Reset(_) => {
self.process_reset();
}
@@ -754,6 +729,7 @@ impl Rule for OddDisconnectionsRule {
EventChild::NumberOfCompletedPackets(nocp) => {
self.process_nocp(&nocp, packet);
}
+
EventChild::AuthenticatedPayloadTimeoutExpired(apte) => {
self.process_apte(&apte, packet);
}
@@ -1008,44 +984,26 @@ impl Rule for LinkKeyMismatchRule {
},
PacketChild::HciCommand(cmd) => match cmd.specialize() {
- CommandChild::AclCommand(cmd) => match cmd.specialize() {
- // Have an arm for Disconnect since sometimes we don't receive disconnect
- // event when powering off. However, no need to actually match the reason
- // since we just clean the handle in both cases.
- AclCommandChild::Disconnect(cmd) => {
- self.process_handle_auth(
- ErrorCode::Success,
- cmd.get_connection_handle(),
- &packet,
- );
- self.handles.remove(&cmd.get_connection_handle());
- }
-
- // CommandChild::AclCommand(cmd).specialize()
- _ => {}
- },
-
- CommandChild::SecurityCommand(cmd) => match cmd.specialize() {
- SecurityCommandChild::LinkKeyRequestReply(cmd) => {
- self.process_reply_link_key(cmd.get_bd_addr(), true);
- }
- SecurityCommandChild::LinkKeyRequestNegativeReply(cmd) => {
- self.process_reply_link_key(cmd.get_bd_addr(), false);
- }
-
- // CommandChild::SecurityCommand(cmd).specialize()
- _ => {}
- },
-
- CommandChild::LeSecurityCommand(cmd) => match cmd.specialize() {
- LeSecurityCommandChild::LeStartEncryption(cmd) => {
- self.pending_le_encrypt.insert(cmd.get_connection_handle());
- }
-
- // CommandChild::LeSecurityCommand(cmd).specialize()
- _ => {}
- },
-
+ // Have an arm for Disconnect since sometimes we don't receive disconnect
+ // event when powering off. However, no need to actually match the reason
+ // since we just clean the handle in both cases.
+ CommandChild::Disconnect(cmd) => {
+ self.process_handle_auth(
+ ErrorCode::Success,
+ cmd.get_connection_handle(),
+ &packet,
+ );
+ self.handles.remove(&cmd.get_connection_handle());
+ }
+ CommandChild::LinkKeyRequestReply(cmd) => {
+ self.process_reply_link_key(cmd.get_bd_addr(), true);
+ }
+ CommandChild::LinkKeyRequestNegativeReply(cmd) => {
+ self.process_reply_link_key(cmd.get_bd_addr(), false);
+ }
+ CommandChild::LeStartEncryption(cmd) => {
+ self.pending_le_encrypt.insert(cmd.get_connection_handle());
+ }
CommandChild::Reset(_) => {
self.process_reset();
}
diff --git a/floss/hcidoc/src/groups/informational.rs b/floss/hcidoc/src/groups/informational.rs
index a8654e7434..dbaa6c8ae3 100644
--- a/floss/hcidoc/src/groups/informational.rs
+++ b/floss/hcidoc/src/groups/informational.rs
@@ -10,8 +10,8 @@ use std::io::Write;
use crate::engine::{Rule, RuleGroup, Signal};
use crate::parser::{get_acl_content, AclContent, Packet, PacketChild};
use hcidoc_packets::hci::{
- AclCommandChild, Address, CommandChild, ConnectionManagementCommandChild, DisconnectReason,
- ErrorCode, EventChild, GapData, GapDataType, LeMetaEventChild,
+ Address, CommandChild, DisconnectReason, ErrorCode, EventChild, GapData, GapDataType,
+ LeMetaEventChild,
};
use hcidoc_packets::l2cap::{ConnectionResponseResult, ControlChild};
@@ -706,18 +706,20 @@ impl InformationalRule {
fn process_raw_gap_data(&mut self, address: &Address, data: &[u8]) {
let mut offset = 0;
while offset < data.len() {
- let chunk_size = usize::from(data[offset]);
- let chunk_end = offset + chunk_size + 1;
-
- // Prevent out-of-bounds index
- if chunk_end > data.len() {
- return;
+ match GapData::parse(&data[offset..]) {
+ Ok(gap_data) => {
+ self.process_gap_data(&address, &gap_data);
+ // advance data len + 2 (size = 1, type = 1)
+ offset += gap_data.data.len() + 2;
+ }
+ Err(err) => {
+ eprintln!("[{}] GAP data is not parsed correctly: {}", address, err);
+ break;
+ }
}
- match GapData::parse(&data[offset..chunk_end]) {
- Ok(gap_data) => self.process_gap_data(&address, &gap_data),
- Err(_err) => {}
+ if offset >= data.len() {
+ break;
}
- offset = chunk_end;
}
}
@@ -804,9 +806,10 @@ impl Rule for InformationalRule {
}
EventChild::ExtendedInquiryResult(ev) => {
- for data in ev.get_extended_inquiry_response() {
- self.process_gap_data(&ev.get_address(), data);
- }
+ self.process_raw_gap_data(
+ &ev.get_address(),
+ ev.get_extended_inquiry_response(),
+ );
self.report_address_type(&ev.get_address(), AddressType::BREDR);
}
@@ -851,16 +854,14 @@ impl Rule for InformationalRule {
self.report_address_type(&ev.get_peer_address(), AddressType::LE);
}
- // Use the Raw version because somehow LeAdvertisingReport doesn't work
- LeMetaEventChild::LeAdvertisingReportRaw(ev) => {
+ LeMetaEventChild::LeAdvertisingReport(ev) => {
for resp in ev.get_responses() {
self.process_raw_gap_data(&resp.address, &resp.advertising_data);
self.report_address_type(&resp.address, AddressType::LE);
}
}
- // Use the Raw version because somehow LeExtendedAdvertisingReport doesn't work
- LeMetaEventChild::LeExtendedAdvertisingReportRaw(ev) => {
+ LeMetaEventChild::LeExtendedAdvertisingReport(ev) => {
for resp in ev.get_responses() {
self.process_raw_gap_data(&resp.address, &resp.advertising_data);
self.report_address_type(&resp.address, AddressType::LE);
@@ -879,37 +880,24 @@ impl Rule for InformationalRule {
CommandChild::Reset(_cmd) => {
self.report_reset(packet.ts);
}
-
- CommandChild::AclCommand(cmd) => match cmd.specialize() {
- AclCommandChild::ConnectionManagementCommand(cmd) => match cmd.specialize() {
- ConnectionManagementCommandChild::CreateConnection(cmd) => {
- self.report_acl_state(&cmd.get_bd_addr(), AclState::Initiating);
- self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR);
- }
-
- ConnectionManagementCommandChild::AcceptConnectionRequest(cmd) => {
- self.report_acl_state(&cmd.get_bd_addr(), AclState::Accepting);
- self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR);
- }
-
- // AclCommandChild::ConnectionManagementCommand(cmd).specialize()
- _ => {}
- },
-
- AclCommandChild::Disconnect(cmd) => {
- // If reason is power off, the host might not wait for connection complete event
- let is_power_off = cmd.get_reason()
- == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff;
- let handle = cmd.get_connection_handle();
- self.pending_disconnections.insert(handle, is_power_off);
- if is_power_off {
- self.report_connection_end(handle, packet.ts);
- }
+ CommandChild::CreateConnection(cmd) => {
+ self.report_acl_state(&cmd.get_bd_addr(), AclState::Initiating);
+ self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR);
+ }
+ CommandChild::AcceptConnectionRequest(cmd) => {
+ self.report_acl_state(&cmd.get_bd_addr(), AclState::Accepting);
+ self.report_address_type(&cmd.get_bd_addr(), AddressType::BREDR);
+ }
+ CommandChild::Disconnect(cmd) => {
+ // If reason is power off, the host might not wait for connection complete event
+ let is_power_off = cmd.get_reason()
+ == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff;
+ let handle = cmd.get_connection_handle();
+ self.pending_disconnections.insert(handle, is_power_off);
+ if is_power_off {
+ self.report_connection_end(handle, packet.ts);
}
-
- // CommandChild::AclCommand(cmd).specialize()
- _ => {}
- },
+ }
// PacketChild::HciCommand(cmd).specialize()
_ => {}