Skip to content
Snippets Groups Projects
Commit 71f3d47b authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Floss: Hcidoc: Add external controller signal" into main

parents c7809876 6529d003
No related branches found
No related tags found
No related merge requests found
...@@ -10,3 +10,4 @@ clap = "4.0" ...@@ -10,3 +10,4 @@ clap = "4.0"
chrono = "0.4" chrono = "0.4"
num-derive = "0.3" num-derive = "0.3"
num-traits = "0.2" num-traits = "0.2"
lazy_static = "1.0"
...@@ -804,6 +804,9 @@ impl Rule for OddDisconnectionsRule { ...@@ -804,6 +804,9 @@ impl Rule for OddDisconnectionsRule {
// We don't do anything with RX packets yet. // We don't do anything with RX packets yet.
PacketChild::AclRx(_) => (), PacketChild::AclRx(_) => (),
// End packet.inner match
_ => (),
} }
} }
......
///! Rule group for tracking controller related issues. ///! Rule group for tracking controller related issues.
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use lazy_static::lazy_static;
use std::collections::HashSet;
use std::convert::Into; use std::convert::Into;
use std::io::Write; use std::io::Write;
use crate::engine::{Rule, RuleGroup, Signal}; use crate::engine::{Rule, RuleGroup, Signal};
use crate::parser::{Packet, PacketChild}; use crate::parser::{NewIndex, Packet, PacketChild};
use bt_packets::hci::EventChild; use bt_packets::hci::{CommandCompleteChild, ErrorCode, EventChild, LocalVersionInformation};
enum ControllerSignal { enum ControllerSignal {
HardwareError, // Controller reports HCI event: Hardware Error HardwareError, // Controller reports HCI event: Hardware Error
LikelyExternalController, // Controller is not in the known list. Likely to be an external controller.
} }
impl Into<&'static str> for ControllerSignal { impl Into<&'static str> for ControllerSignal {
fn into(self) -> &'static str { fn into(self) -> &'static str {
match self { match self {
ControllerSignal::HardwareError => "HardwareError", ControllerSignal::HardwareError => "HardwareError",
ControllerSignal::LikelyExternalController => "LikelyExternalController",
} }
} }
} }
lazy_static! {
static ref KNOWN_CONTROLLER_NAMES: [String; 6] = [
String::from("Bluemoon Universal Bluetooth Host Controller"), // AC7625
String::from("MTK MT7961 #1"), // MT7921LE/MT7921LS
String::from("MTK MT7922 #1"), // MT7922
String::from("RTK_BT_5.0"), // RTL8822CE
String::from("RT_BT"), // RTL8852AE
String::from(""), // AC9260/AC9560/AX200/AX201/AX203/AX211/MVL8897/QCA6174A3/QCA6174A5/QC_WCN6856
];
}
const KNOWN_CONTROLLER_MANUFACTURERS: [u16; 5] = [
2, // Intel.
29, // Qualcomm
70, // MediaTek
72, // Marvell
93, // Realtek
];
struct ControllerRule { struct ControllerRule {
/// Pre-defined signals discovered in the logs. /// Pre-defined signals discovered in the logs.
signals: Vec<Signal>, signals: Vec<Signal>,
/// Interesting occurrences surfaced by this rule. /// Interesting occurrences surfaced by this rule.
reportable: Vec<(NaiveDateTime, String)>, reportable: Vec<(NaiveDateTime, String)>,
/// All detected open_index.
controllers: HashSet<String>,
} }
impl ControllerRule { impl ControllerRule {
pub fn new() -> Self { pub fn new() -> Self {
ControllerRule { signals: vec![], reportable: vec![] } ControllerRule { signals: vec![], reportable: vec![], controllers: HashSet::new() }
} }
pub fn report_hardware_error(&mut self, packet: &Packet) { pub fn report_hardware_error(&mut self, packet: &Packet) {
...@@ -41,6 +66,48 @@ impl ControllerRule { ...@@ -41,6 +66,48 @@ impl ControllerRule {
self.reportable.push((packet.ts, format!("controller reported hardware error"))); self.reportable.push((packet.ts, format!("controller reported hardware error")));
} }
fn process_local_name(&mut self, local_name: &[u8; 248], packet: &Packet) {
let null_index = local_name.iter().position(|&b| b == 0).unwrap_or(local_name.len());
match String::from_utf8(local_name[..null_index].to_vec()) {
Ok(name) => {
if !KNOWN_CONTROLLER_NAMES.contains(&name) {
self.signals.push(Signal {
index: packet.index,
ts: packet.ts,
tag: ControllerSignal::LikelyExternalController.into(),
})
}
}
Err(_) => self.signals.push(Signal {
index: packet.index,
ts: packet.ts,
tag: ControllerSignal::LikelyExternalController.into(),
}),
}
}
fn process_local_version(&mut self, version_info: &LocalVersionInformation, packet: &Packet) {
if !KNOWN_CONTROLLER_MANUFACTURERS.contains(&version_info.manufacturer_name) {
self.signals.push(Signal {
index: packet.index,
ts: packet.ts,
tag: ControllerSignal::LikelyExternalController.into(),
})
}
}
fn process_new_index(&mut self, new_index: &NewIndex, packet: &Packet) {
self.controllers.insert(new_index.get_addr_str());
if self.controllers.len() > 1 {
self.signals.push(Signal {
index: packet.index,
ts: packet.ts,
tag: ControllerSignal::LikelyExternalController.into(),
});
}
}
} }
impl Rule for ControllerRule { impl Rule for ControllerRule {
...@@ -50,8 +117,28 @@ impl Rule for ControllerRule { ...@@ -50,8 +117,28 @@ impl Rule for ControllerRule {
EventChild::HardwareError(_ev) => { EventChild::HardwareError(_ev) => {
self.report_hardware_error(&packet); self.report_hardware_error(&packet);
} }
EventChild::CommandComplete(ev) => match ev.specialize() {
CommandCompleteChild::ReadLocalNameComplete(ev) => {
if ev.get_status() != ErrorCode::Success {
return;
}
self.process_local_name(ev.get_local_name(), &packet);
}
CommandCompleteChild::ReadLocalVersionInformationComplete(ev) => {
if ev.get_status() != ErrorCode::Success {
return;
}
self.process_local_version(ev.get_local_version_information(), &packet);
}
_ => {}
},
_ => {} _ => {}
}, },
PacketChild::NewIndex(ni) => {
self.process_new_index(ni, &packet);
}
_ => {} _ => {}
} }
} }
......
...@@ -931,7 +931,10 @@ impl Rule for InformationalRule { ...@@ -931,7 +931,10 @@ impl Rule for InformationalRule {
// PacketChild::AclRx(rx).specialize() // PacketChild::AclRx(rx).specialize()
_ => {} _ => {}
} }
} // packet.inner }
// End packet.inner match
_ => (),
} }
} }
......
...@@ -287,6 +287,7 @@ pub enum PacketChild { ...@@ -287,6 +287,7 @@ pub enum PacketChild {
HciEvent(Event), HciEvent(Event),
AclTx(Acl), AclTx(Acl),
AclRx(Acl), AclRx(Acl),
NewIndex(NewIndex),
} }
impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild { impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild {
...@@ -314,6 +315,11 @@ impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild { ...@@ -314,6 +315,11 @@ impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild {
Err(e) => Err(format!("Couldn't parse acl rx: {:?}", e)), Err(e) => Err(format!("Couldn't parse acl rx: {:?}", e)),
}, },
LinuxSnoopOpcodes::NewIndex => match NewIndex::parse(item.data.as_slice()) {
Ok(data) => Ok(PacketChild::NewIndex(data)),
Err(e) => Err(format!("Couldn't parse new index: {:?}", e)),
},
// TODO(b/262928525) - Add packet handlers for more packet types. // TODO(b/262928525) - Add packet handlers for more packet types.
_ => Err(format!("Unhandled packet opcode: {:?}", item.opcode())), _ => Err(format!("Unhandled packet opcode: {:?}", item.opcode())),
} }
...@@ -400,3 +406,44 @@ pub fn get_acl_content(acl: &Acl) -> AclContent { ...@@ -400,3 +406,44 @@ pub fn get_acl_content(acl: &Acl) -> AclContent {
_ => AclContent::None, _ => AclContent::None,
} }
} }
#[derive(Clone, Debug)]
pub struct NewIndex {
_hci_type: u8,
_bus: u8,
bdaddr: [u8; 6],
_name: [u8; 8],
}
impl NewIndex {
fn parse(data: &[u8]) -> Result<NewIndex, std::string::String> {
if data.len() != std::mem::size_of::<NewIndex>() {
return Err(format!("Invalid size for New Index packet: {}", data.len()));
}
let rest = data;
let (hci_type, rest) = rest.split_at(std::mem::size_of::<u8>());
let (bus, rest) = rest.split_at(std::mem::size_of::<u8>());
let (bdaddr, rest) = rest.split_at(6 * std::mem::size_of::<u8>());
let (name, _rest) = rest.split_at(8 * std::mem::size_of::<u8>());
Ok(NewIndex {
_hci_type: hci_type[0],
_bus: bus[0],
bdaddr: bdaddr.try_into().unwrap(),
_name: name.try_into().unwrap(),
})
}
pub fn get_addr_str(&self) -> String {
String::from(format!(
"[{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}]",
self.bdaddr[0],
self.bdaddr[1],
self.bdaddr[2],
self.bdaddr[3],
self.bdaddr[4],
self.bdaddr[5]
))
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment