Skip to content

Commit

Permalink
Merge "Floss: Hcidoc: Add external controller signal" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Treehugger Robot authored and Gerrit Code Review committed Feb 29, 2024
2 parents c780987 + 6529d00 commit 71f3d47
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 5 deletions.
1 change: 1 addition & 0 deletions floss/hcidoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ clap = "4.0"
chrono = "0.4"
num-derive = "0.3"
num-traits = "0.2"
lazy_static = "1.0"
3 changes: 3 additions & 0 deletions floss/hcidoc/src/groups/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,9 @@ impl Rule for OddDisconnectionsRule {

// We don't do anything with RX packets yet.
PacketChild::AclRx(_) => (),

// End packet.inner match
_ => (),
}
}

Expand Down
95 changes: 91 additions & 4 deletions floss/hcidoc/src/groups/controllers.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
///! Rule group for tracking controller related issues.
use chrono::NaiveDateTime;
use lazy_static::lazy_static;
use std::collections::HashSet;
use std::convert::Into;
use std::io::Write;

use crate::engine::{Rule, RuleGroup, Signal};
use crate::parser::{Packet, PacketChild};
use bt_packets::hci::EventChild;
use crate::parser::{NewIndex, Packet, PacketChild};
use bt_packets::hci::{CommandCompleteChild, ErrorCode, EventChild, LocalVersionInformation};

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 {
fn into(self) -> &'static str {
match self {
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 {
/// Pre-defined signals discovered in the logs.
signals: Vec<Signal>,

/// Interesting occurrences surfaced by this rule.
reportable: Vec<(NaiveDateTime, String)>,

/// All detected open_index.
controllers: HashSet<String>,
}

impl ControllerRule {
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) {
Expand All @@ -41,6 +66,48 @@ impl ControllerRule {

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 {
Expand All @@ -50,8 +117,28 @@ impl Rule for ControllerRule {
EventChild::HardwareError(_ev) => {
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);
}
_ => {}
}
}
Expand Down
5 changes: 4 additions & 1 deletion floss/hcidoc/src/groups/informational.rs
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,10 @@ impl Rule for InformationalRule {
// PacketChild::AclRx(rx).specialize()
_ => {}
}
} // packet.inner
}

// End packet.inner match
_ => (),
}
}

Expand Down
47 changes: 47 additions & 0 deletions floss/hcidoc/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ pub enum PacketChild {
HciEvent(Event),
AclTx(Acl),
AclRx(Acl),
NewIndex(NewIndex),
}

impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild {
Expand Down Expand Up @@ -314,6 +315,11 @@ impl<'a> TryFrom<&'a LinuxSnoopPacket> for PacketChild {
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.
_ => Err(format!("Unhandled packet opcode: {:?}", item.opcode())),
}
Expand Down Expand Up @@ -400,3 +406,44 @@ pub fn get_acl_content(acl: &Acl) -> AclContent {
_ => 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 comments on commit 71f3d47

Please sign in to comment.