Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cc57fc4 authored by Michael Sun's avatar Michael Sun Committed by Mingguang Xu
Browse files

btaa: HCI classic event process

Introduce BTAA HCI event processing. This change only handles simple
(event that contains only one device information and do not require
additional processing )classic events. Command status and command
complete events will be associated with previous parsed HCI command.

The lookup table is a skelton implementation that does not contain 100%
correct information.

Tag: #feature
Bug: 177230507
Test: verified locally BTAA can partially process HCI events.
BYPASS_LONG_LINES_REASON: consist with gd format

Change-Id: Idd26318200cfd1f94596dd69083452dba5dff478
parent 4b537e91
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct CmdEvtActivityClassification {
};

CmdEvtActivityClassification lookup_cmd(hci::OpCode opcode);
CmdEvtActivityClassification lookup_event(hci::EventCode event_code);

}  // namespace activity_attribution
}  // namespace bluetooth
+70 −0
Original line number Diff line number Diff line
@@ -327,5 +327,75 @@ CmdEvtActivityClassification lookup_cmd(hci::OpCode opcode) {
  return classification;
}

CmdEvtActivityClassification lookup_event(hci::EventCode event_code) {
  CmdEvtActivityClassification classification = {};
  switch (event_code) {
    case hci::EventCode::INQUIRY_COMPLETE:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 0};
      break;
    case hci::EventCode::CONNECTION_COMPLETE:
    case hci::EventCode::SYNCHRONOUS_CONNECTION_COMPLETE:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 3, .address_pos = 5};
      break;

    case hci::EventCode::CONNECTION_REQUEST:
    case hci::EventCode::PIN_CODE_REQUEST:
    case hci::EventCode::LINK_KEY_REQUEST:
    case hci::EventCode::LINK_KEY_NOTIFICATION:
    case hci::EventCode::USER_PASSKEY_NOTIFICATION:
    case hci::EventCode::KEYPRESS_NOTIFICATION:
    case hci::EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION:
    case hci::EventCode::IO_CAPABILITY_REQUEST:
    case hci::EventCode::IO_CAPABILITY_RESPONSE:
    case hci::EventCode::USER_CONFIRMATION_REQUEST:
    case hci::EventCode::USER_PASSKEY_REQUEST:
    case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 2};
      break;

    case hci::EventCode::DISCONNECTION_COMPLETE:
    case hci::EventCode::AUTHENTICATION_COMPLETE:
    case hci::EventCode::ENCRYPTION_CHANGE:
    case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
    case hci::EventCode::LINK_SUPERVISION_TIMEOUT_CHANGED:
    case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
    case hci::EventCode::CENTRAL_LINK_KEY_COMPLETE:
    case hci::EventCode::READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
    case hci::EventCode::READ_REMOTE_VERSION_INFORMATION_COMPLETE:
    case hci::EventCode::QOS_SETUP_COMPLETE:
    case hci::EventCode::MODE_CHANGE:
    case hci::EventCode::READ_CLOCK_OFFSET_COMPLETE:
    case hci::EventCode::CONNECTION_PACKET_TYPE_CHANGED:
    case hci::EventCode::FLOW_SPECIFICATION_COMPLETE:
    case hci::EventCode::READ_REMOTE_EXTENDED_FEATURES_COMPLETE:
    case hci::EventCode::SYNCHRONOUS_CONNECTION_CHANGED:
    case hci::EventCode::SNIFF_SUBRATING:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 3, .address_pos = 0};
      break;

    case hci::EventCode::REMOTE_NAME_REQUEST_COMPLETE:
    case hci::EventCode::EXTENDED_INQUIRY_RESULT:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 3};
      break;
    case hci::EventCode::FLUSH_OCCURRED:
    case hci::EventCode::MAX_SLOTS_CHANGE:
    case hci::EventCode::QOS_VIOLATION:
    case hci::EventCode::ENHANCED_FLUSH_COMPLETE:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 2, .address_pos = 0};
      break;
    case hci::EventCode::ROLE_CHANGE:
    case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
      classification = {.activity = Activity::CONNECT, .connection_handle_pos = 0, .address_pos = 3};
      break;
    case hci::EventCode::PAGE_SCAN_REPETITION_MODE_CHANGE:
      classification = {.activity = Activity::SCAN, .connection_handle_pos = 0, .address_pos = 2};
      break;

    default:
      classification = {.activity = Activity::UNKNOWN, .connection_handle_pos = 0, .address_pos = 0};
  }
  return classification;
}

}  // namespace activity_attribution
}  // namespace bluetooth
+68 −3
Original line number Diff line number Diff line
@@ -38,8 +38,13 @@ class DeviceParser {
  std::map<uint16_t, hci::Address> connection_lookup_table;
};

struct PendingCommand {
  hci::OpCode opcode;
  BtaaHciPacket btaa_hci_packet;
};

static DeviceParser device_parser;
static std::pair<hci::OpCode, BtaaHciPacket> pending_command;
static PendingCommand pending_command;

static void process_command(
    std::vector<BtaaHciPacket>& btaa_hci_packets,
@@ -64,9 +69,68 @@ static void process_command(
    address_value = address_value_it.extract<hci::Address>();
  }
  device_parser.match_handle_with_address(connection_handle_value, address_value);
  pending_command.second = BtaaHciPacket(cmd_info.activity, address_value, byte_count);
  pending_command.btaa_hci_packet = BtaaHciPacket(cmd_info.activity, address_value, byte_count);

  pending_command.opcode = opcode;
}

static void process_event(
    std::vector<BtaaHciPacket>& btaa_hci_packets,
    packet::PacketView<packet::kLittleEndian>& packet_view,
    uint16_t byte_count) {
  hci::EventView event = hci::EventView::Create(packet_view);
  if (!event.IsValid()) {
    return;
  }

  pending_command.first = opcode;
  uint16_t connection_handle_value = 0;
  hci::Address address_value;
  auto event_code = event.GetEventCode();
  auto event_info = lookup_event(event_code);

  if (event_info.activity != Activity::UNKNOWN) {
    // lookup_event returns all simple classic event which does not require additional processing.
    if (event_info.connection_handle_pos) {
      auto connection_handle_it = event.begin() + event_info.connection_handle_pos;
      connection_handle_value = connection_handle_it.extract<uint16_t>();
    }
    if (event_info.address_pos) {
      auto address_value_it = event.begin() + event_info.address_pos;
      address_value = address_value_it.extract<hci::Address>();
    }
    device_parser.match_handle_with_address(connection_handle_value, address_value);
    btaa_hci_packets.push_back(BtaaHciPacket(event_info.activity, address_value, byte_count));
  } else {
    // The event requires additional processing.
    switch (event_code) {
      case hci::EventCode::COMMAND_COMPLETE: {
        auto packet_view = hci::CommandCompleteView::Create(event);
        if (packet_view.IsValid() && packet_view.GetCommandOpCode() == pending_command.opcode) {
          pending_command.btaa_hci_packet.byte_count += byte_count;
          btaa_hci_packets.push_back(std::move(pending_command.btaa_hci_packet));
        } else {
          btaa_hci_packets.push_back(BtaaHciPacket(Activity::UNKNOWN, address_value, byte_count));
        }
      } break;
      case hci::EventCode::COMMAND_STATUS: {
        auto packet_view = hci::CommandStatusView::Create(event);
        if (packet_view.IsValid() && packet_view.GetCommandOpCode() == pending_command.opcode) {
          pending_command.btaa_hci_packet.byte_count += byte_count;
          btaa_hci_packets.push_back(std::move(pending_command.btaa_hci_packet));
        } else {
          btaa_hci_packets.push_back(BtaaHciPacket(Activity::UNKNOWN, address_value, byte_count));
        }
        break;
      }
      case hci::EventCode::LE_META_EVENT:
        break;
      case hci::EventCode::VENDOR_SPECIFIC:
        btaa_hci_packets.push_back(BtaaHciPacket(Activity::VENDOR, address_value, byte_count));
        break;
      default:
        break;
    }
  }
}

std::vector<BtaaHciPacket> HciProcessor::OnHciPacket(
@@ -78,6 +142,7 @@ std::vector<BtaaHciPacket> HciProcessor::OnHciPacket(
      process_command(btaa_hci_packets, packet_view, length);
      break;
    case hal::SnoopLogger::PacketType::EVT:
      process_event(btaa_hci_packets, packet_view, length);
      break;
    case hal::SnoopLogger::PacketType::ACL:
      break;