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

Commit 6788e3ec authored by Henri Chataing's avatar Henri Chataing
Browse files

RootCanal: Refactor LE scanning commands

Implement HCI parameter validation as required by the specification.
Resolve or generate private addresses when required in
6.B.6.3 Privacy in scanning state.

Test: atest --host --no-bazel rootcanal_hci_test
Change-Id: Ice2e2e46b8ca157ca1b4131d0c7a642a2074ddc6
parent c411f010
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -135,6 +135,10 @@ cc_test_host {
        "test/controller/le/le_set_address_resolution_enable_test.cc",
        "test/controller/le/le_set_advertising_parameters_test.cc",
        "test/controller/le/le_set_advertising_enable_test.cc",
        "test/controller/le/le_set_scan_parameters_test.cc",
        "test/controller/le/le_set_scan_enable_test.cc",
        "test/controller/le/le_set_extended_scan_parameters_test.cc",
        "test/controller/le/le_set_extended_scan_enable_test.cc",
    ],
    header_libs: [
        "libbluetooth_headers",
+29 −53
Original line number Diff line number Diff line
@@ -2129,9 +2129,10 @@ void DualModeController::LeSetAdvertisingData(CommandView command) {
  ASSERT_LOG(command_view.IsValid(), "%s command.size() = %zu",
             gd_hci::OpCodeText(command.GetOpCode()).c_str(), command.size());
  ASSERT(command_view.GetPayload().size() == 32);
  ErrorCode status =
      link_layer_controller_.LeSetAdvertisingData(advertising_data);
  send_event_(bluetooth::hci::LeSetAdvertisingDataCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS));
      kNumCommandPackets, status));
}

void DualModeController::LeSetScanResponseData(CommandView command) {
@@ -2139,10 +2140,11 @@ void DualModeController::LeSetScanResponseData(CommandView command) {
      gd_hci::LeAdvertisingCommandView::Create(command));
  ASSERT(command_view.IsValid());
  ASSERT(command_view.GetPayload().size() == 32);
  link_layer_controller_.LeSetScanResponseData(std::vector<uint8_t>(
      command_view.GetPayload().begin() + 1, command_view.GetPayload().end()));
  ErrorCode status = link_layer_controller_.LeSetScanResponseData(
      std::vector<uint8_t>(command_view.GetPayload().begin() + 1,
                           command_view.GetPayload().end()));
  send_event_(bluetooth::hci::LeSetScanResponseDataCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS));
      kNumCommandPackets, status));
}

void DualModeController::LeSetAdvertisingEnable(CommandView command) {
@@ -2163,15 +2165,13 @@ void DualModeController::LeSetScanParameters(CommandView command) {
  auto command_view = gd_hci::LeSetScanParametersView::Create(
      gd_hci::LeScanningCommandView::Create(command));
  ASSERT(command_view.IsValid());
  link_layer_controller_.SetLeScanType(
      static_cast<uint8_t>(command_view.GetLeScanType()));
  link_layer_controller_.SetLeScanInterval(command_view.GetLeScanInterval());
  link_layer_controller_.SetLeScanWindow(command_view.GetLeScanWindow());
  link_layer_controller_.SetLeAddressType(command_view.GetOwnAddressType());
  link_layer_controller_.SetLeScanFilterPolicy(

  ErrorCode status = link_layer_controller_.LeSetScanParameters(
      command_view.GetLeScanType(), command_view.GetLeScanInterval(),
      command_view.GetLeScanWindow(), command_view.GetOwnAddressType(),
      command_view.GetScanningFilterPolicy());
  send_event_(bluetooth::hci::LeSetScanParametersCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS));
      kNumCommandPackets, status));
}

void DualModeController::LeSetScanEnable(CommandView command) {
@@ -2182,15 +2182,11 @@ void DualModeController::LeSetScanEnable(CommandView command) {
  LOG_INFO("%s | LeSetScanEnable (%d)", GetAddress().ToString().c_str(),
           command_view.GetLeScanEnable() == gd_hci::Enable::ENABLED);

  if (command_view.GetLeScanEnable() == gd_hci::Enable::ENABLED) {
    link_layer_controller_.SetLeScanEnable(gd_hci::OpCode::LE_SET_SCAN_ENABLE);
  } else {
    link_layer_controller_.SetLeScanEnable(gd_hci::OpCode::NONE);
  }
  link_layer_controller_.SetLeFilterDuplicates(
  ErrorCode status = link_layer_controller_.LeSetScanEnable(
      command_view.GetLeScanEnable() == gd_hci::Enable::ENABLED,
      command_view.GetFilterDuplicates() == gd_hci::Enable::ENABLED);
  send_event_(bluetooth::hci::LeSetScanEnableCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS));
      kNumCommandPackets, status));
}

void DualModeController::LeCreateConnection(CommandView command) {
@@ -2207,11 +2203,8 @@ void DualModeController::LeCreateConnection(CommandView command) {
  if (initiator_filter_policy ==
      bluetooth::hci::InitiatorFilterPolicy::USE_PEER_ADDRESS) {
    // Connect list not used
    uint8_t peer_address_type =
        static_cast<uint8_t>(command_view.GetPeerAddressType());
    Address peer_address = command_view.GetPeerAddress();
    link_layer_controller_.SetLePeerAddressType(peer_address_type);
    link_layer_controller_.SetLePeerAddress(peer_address);
    link_layer_controller_.SetLePeerAddress(AddressWithType{
        command_view.GetPeerAddress(), command_view.GetPeerAddressType()});
  }
  link_layer_controller_.SetLeAddressType(command_view.GetOwnAddressType());
  link_layer_controller_.SetLeConnectionIntervalMin(
@@ -2454,23 +2447,9 @@ void DualModeController::LeSetExtendedScanParameters(CommandView command) {
  auto command_view = gd_hci::LeSetExtendedScanParametersView::Create(
      gd_hci::LeScanningCommandView::Create(command));
  ASSERT(command_view.IsValid());
  auto parameters = command_view.GetParameters();
  // Multiple phys are not supported.
  ASSERT(command_view.GetScanningPhys() == 1);
  ASSERT(parameters.size() == 1);

  auto status = ErrorCode::SUCCESS;
  if (link_layer_controller_.GetLeScanEnable() == OpCode::NONE) {
    link_layer_controller_.SetLeScanType(
        static_cast<uint8_t>(parameters[0].le_scan_type_));
    link_layer_controller_.SetLeScanInterval(parameters[0].le_scan_interval_);
    link_layer_controller_.SetLeScanWindow(parameters[0].le_scan_window_);
    link_layer_controller_.SetLeAddressType(command_view.GetOwnAddressType());
    link_layer_controller_.SetLeScanFilterPolicy(
        command_view.GetScanningFilterPolicy());
  } else {
    status = ErrorCode::COMMAND_DISALLOWED;
  }
  ErrorCode status = link_layer_controller_.LeSetExtendedScanParameters(
      command_view.GetOwnAddressType(), command_view.GetScanningFilterPolicy(),
      command_view.GetScanningPhys(), command_view.GetParameters());
  send_event_(
      bluetooth::hci::LeSetExtendedScanParametersCompleteBuilder::Create(
          kNumCommandPackets, status));
@@ -2480,16 +2459,12 @@ void DualModeController::LeSetExtendedScanEnable(CommandView command) {
  auto command_view = gd_hci::LeSetExtendedScanEnableView::Create(
      gd_hci::LeScanningCommandView::Create(command));
  ASSERT(command_view.IsValid());
  if (command_view.GetEnable() == gd_hci::Enable::ENABLED) {
    link_layer_controller_.SetLeScanEnable(
        gd_hci::OpCode::LE_SET_EXTENDED_SCAN_ENABLE);
  } else {
    link_layer_controller_.SetLeScanEnable(gd_hci::OpCode::NONE);
  }
  link_layer_controller_.SetLeFilterDuplicates(
      command_view.GetFilterDuplicates() == gd_hci::FilterDuplicates::ENABLED);
  ErrorCode status = link_layer_controller_.LeSetExtendedScanEnable(
      command_view.GetEnable() == gd_hci::Enable::ENABLED,
      command_view.GetFilterDuplicates(), command_view.GetDuration(),
      command_view.GetPeriod());
  send_event_(bluetooth::hci::LeSetExtendedScanEnableCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS));
      kNumCommandPackets, status));
}

void DualModeController::LeExtendedCreateConnection(CommandView command) {
@@ -2507,9 +2482,10 @@ void DualModeController::LeExtendedCreateConnection(CommandView command) {

  if (initiator_filter_policy ==
      gd_hci::InitiatorFilterPolicy::USE_PEER_ADDRESS) {
    link_layer_controller_.SetLePeerAddressType(
        static_cast<uint8_t>(command_view.GetPeerAddressType()));
    link_layer_controller_.SetLePeerAddress(command_view.GetPeerAddress());
    link_layer_controller_.SetLePeerAddress(AddressWithType{
        command_view.GetPeerAddress(),
        command_view.GetPeerAddressType(),
    });
  }
  link_layer_controller_.SetLeAddressType(command_view.GetOwnAddressType());
  link_layer_controller_.SetLeConnectionIntervalMin(
+42 −4
Original line number Diff line number Diff line
@@ -50,6 +50,15 @@ ErrorCode LinkLayerController::LeSetAdvertisingParameters(
    PeerAddressType peer_address_type, Address peer_address,
    uint8_t advertising_channel_map,
    AdvertisingFilterPolicy advertising_filter_policy) {
  // Legacy advertising commands are disallowed when extended advertising
  // commands were used since the last reset.
  if (!SelectLegacyAdvertising()) {
    LOG_INFO(
        "legacy advertising command rejected because extended advertising"
        " is being used");
    return ErrorCode::COMMAND_DISALLOWED;
  }

  // Clear reserved bits.
  advertising_channel_map &= 0x7;

@@ -118,21 +127,47 @@ ErrorCode LinkLayerController::LeSetAdvertisingParameters(
}

// HCI command LE_Set_Advertising_Data (Vol 4, Part E § 7.8.7).
void LinkLayerController::LeSetAdvertisingData(
ErrorCode LinkLayerController::LeSetAdvertisingData(
    const std::vector<uint8_t>& advertising_data) {
  // Legacy advertising commands are disallowed when extended advertising
  // commands were used since the last reset.
  if (!SelectLegacyAdvertising()) {
    LOG_INFO(
        "legacy advertising command rejected because extended advertising"
        " is being used");
    return ErrorCode::COMMAND_DISALLOWED;
  }

  legacy_advertiser_.advertising_data = advertising_data;
  return ErrorCode::SUCCESS;
}

// HCI command LE_Set_Scan_Response_Data (Vol 4, Part E § 7.8.8).
void LinkLayerController::LeSetScanResponseData(
ErrorCode LinkLayerController::LeSetScanResponseData(
    const std::vector<uint8_t>& scan_response_data) {
  // Legacy advertising commands are disallowed when extended advertising
  // commands were used since the last reset.
  if (!SelectLegacyAdvertising()) {
    LOG_INFO(
        "legacy advertising command rejected because extended advertising"
        " is being used");
    return ErrorCode::COMMAND_DISALLOWED;
  }

  legacy_advertiser_.scan_response_data = scan_response_data;
  return ErrorCode::SUCCESS;
}

// HCI command LE_Advertising_Enable (Vol 4, Part E § 7.8.9).
ErrorCode LinkLayerController::LeSetAdvertisingEnable(bool advertising_enable) {
  // Note: additional checks would apply in the case of a LE only Controller
  // with no configured public device address.
  // Legacy advertising commands are disallowed when extended advertising
  // commands were used since the last reset.
  if (!SelectLegacyAdvertising()) {
    LOG_INFO(
        "legacy advertising command rejected because extended advertising"
        " is being used");
    return ErrorCode::COMMAND_DISALLOWED;
  }

  if (!advertising_enable) {
    legacy_advertiser_.advertising_enable = false;
@@ -147,6 +182,9 @@ ErrorCode LinkLayerController::LeSetAdvertisingEnable(bool advertising_enable) {
  std::optional<AddressWithType> resolvable_address =
      GenerateResolvablePrivateAddress(peer_address, IrkSelection::Local);

  // TODO: additional checks would apply in the case of a LE only Controller
  // with no configured public device address.

  switch (legacy_advertiser_.own_address_type) {
    case OwnAddressType::PUBLIC_DEVICE_ADDRESS:
      legacy_advertiser_.advertising_address = public_address;
+593 −101

File changed.

Preview size limit exceeded, changes collapsed.

+127 −33
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ class LinkLayerController {
  void Reset();

  void LeAdvertising();
  void LeScanning();

  ErrorCode SetLeExtendedAddress(uint8_t handle, Address address);

@@ -243,6 +244,19 @@ class LinkLayerController {
  std::optional<AddressWithType> GenerateResolvablePrivateAddress(
      AddressWithType address, IrkSelection irk);

  // Check if the selected address matches one of the controller's device
  // addresses (public or random static).
  bool IsLocalPublicOrRandomAddress(AddressWithType address) {
    switch (address.GetAddressType()) {
      case AddressType::PUBLIC_DEVICE_ADDRESS:
        return address.GetAddress() == address_;
      case AddressType::RANDOM_DEVICE_ADDRESS:
        return address.GetAddress() == random_address_;
      default:
        return false;
    }
  }

  void LeReadIsoTxSync(uint16_t handle);
  void LeSetCigParameters(
      uint8_t cig_id, uint32_t sdu_interval_m_to_s,
@@ -300,25 +314,6 @@ class LinkLayerController {
      bluetooth::hci::Enable enable,
      const std::vector<bluetooth::hci::EnabledSet>& enabled_sets);

  bluetooth::hci::OpCode GetLeScanEnable() { return le_scan_enable_; }

  void SetLeScanEnable(bluetooth::hci::OpCode enabling_opcode) {
    le_scan_enable_ = enabling_opcode;
  }
  void SetLeScanType(uint8_t le_scan_type) { le_scan_type_ = le_scan_type; }
  void SetLeScanInterval(uint16_t le_scan_interval) {
    le_scan_interval_ = le_scan_interval;
  }
  void SetLeScanWindow(uint16_t le_scan_window) {
    le_scan_window_ = le_scan_window;
  }
  void SetLeScanFilterPolicy(
      bluetooth::hci::LeScanningFilterPolicy le_scan_filter_policy) {
    le_scan_filter_policy_ = le_scan_filter_policy;
  }
  void SetLeFilterDuplicates(uint8_t le_scan_filter_duplicates) {
    le_scan_filter_duplicates_ = le_scan_filter_duplicates;
  }
  void SetLeAddressType(bluetooth::hci::OwnAddressType le_address_type) {
    le_address_type_ = le_address_type;
  }
@@ -353,13 +348,17 @@ class LinkLayerController {
      bluetooth::hci::InitiatorFilterPolicy le_initiator_filter_policy) {
    le_initiator_filter_policy_ = le_initiator_filter_policy;
  }
  void SetLePeerAddressType(uint8_t peer_address_type) {
    le_peer_address_type_ = peer_address_type;
  }
  void SetLePeerAddress(const Address& peer_address) {
  void SetLePeerAddress(const AddressWithType& peer_address) {
    le_peer_address_ = peer_address;
  }

  void SetLeScanInterval(uint16_t le_scan_interval) {
    le_scan_interval_ = le_scan_interval;
  }
  void SetLeScanWindow(uint16_t le_scan_window) {
    le_scan_window_ = le_scan_window;
  }

  // Classic
  void StartInquiry(std::chrono::milliseconds timeout);
  void InquiryCancel();
@@ -479,14 +478,40 @@ class LinkLayerController {
      bluetooth::hci::AdvertisingFilterPolicy advertising_filter_policy);

  // HCI command LE_Set_Advertising_Data (Vol 4, Part E § 7.8.7).
  void LeSetAdvertisingData(const std::vector<uint8_t>& advertising_data);
  ErrorCode LeSetAdvertisingData(const std::vector<uint8_t>& advertising_data);

  // HCI command LE_Set_Scan_Response_Data (Vol 4, Part E § 7.8.8).
  void LeSetScanResponseData(const std::vector<uint8_t>& scan_response_data);
  ErrorCode LeSetScanResponseData(
      const std::vector<uint8_t>& scan_response_data);

  // HCI command LE_Advertising_Enable (Vol 4, Part E § 7.8.9).
  ErrorCode LeSetAdvertisingEnable(bool advertising_enable);

  // Legacy Scanning

  // HCI command LE_Set_Scan_Parameters (Vol 4, Part E § 7.8.10).
  ErrorCode LeSetScanParameters(
      bluetooth::hci::LeScanType scan_type, uint16_t scan_interval,
      uint16_t scan_window, bluetooth::hci::OwnAddressType own_address_type,
      bluetooth::hci::LeScanningFilterPolicy scanning_filter_policy);

  // HCI command LE_Set_Scan_Enable (Vol 4, Part E § 7.8.11).
  ErrorCode LeSetScanEnable(bool enable, bool filter_duplicates);

  // Extended Scanning

  // HCI command LE_Set_Extended_Scan_Parameters (Vol 4, Part E § 7.8.64).
  ErrorCode LeSetExtendedScanParameters(
      bluetooth::hci::OwnAddressType own_address_type,
      bluetooth::hci::LeScanningFilterPolicy scanning_filter_policy,
      uint8_t scanning_phys,
      std::vector<bluetooth::hci::PhyScanParameters> scanning_phy_parameters);

  // HCI command LE_Set_Extended_Scan_Enable (Vol 4, Part E § 7.8.65).
  ErrorCode LeSetExtendedScanEnable(
      bool enable, bluetooth::hci::FilterDuplicates filter_duplicates,
      uint16_t duration, uint16_t period);

 protected:
  void SendLeLinkLayerPacketWithRssi(
      Address source, Address dest, uint8_t rssi,
@@ -528,6 +553,11 @@ class LinkLayerController {
  void IncomingIsoConnectionResponsePacket(
      model::packets::LinkLayerPacketView packet);

  void ScanIncomingLeLegacyAdvertisingPdu(
      model::packets::LeLegacyAdvertisingPduView& pdu, uint8_t rssi);
  void ConnectIncomingLeLegacyAdvertisingPdu(
      model::packets::LeLegacyAdvertisingPduView& pdu);

  void IncomingLeLegacyAdvertisingPdu(
      model::packets::LinkLayerPacketView packet, uint8_t rssi);
  void IncomingLeExtendedAdvertisingPdu(
@@ -673,6 +703,27 @@ class LinkLayerController {
    connection_accept_timeout_ = timeout;
  }

  bool LegacyAdvertising() const { return legacy_advertising_in_use_; }
  bool ExtendedAdvertising() const { return extended_advertising_in_use_; }

  bool SelectLegacyAdvertising() {
    if (extended_advertising_in_use_) {
      return false;
    } else {
      legacy_advertising_in_use_ = true;
      return true;
    }
  }

  bool SelectExtendedAdvertising() {
    if (legacy_advertising_in_use_) {
      return false;
    } else {
      extended_advertising_in_use_ = true;
      return true;
    }
  }

 private:
  const Address& address_;
  const ControllerProperties& properties_;
@@ -801,19 +852,63 @@ class LinkLayerController {
  std::vector<ResolvingListEntry> le_resolving_list_;
  bool le_resolving_list_enabled_{false};

  // Flag set when any legacy advertising command has been received
  // since the last power-on-reset.
  // From Vol 4, Part E § 3.1.1 Legacy and extended advertising,
  // extended advertising are rejected when this bit is set.
  bool legacy_advertising_in_use_{false};

  // Flag set when any extended advertising command has been received
  // since the last power-on-reset.
  // From Vol 4, Part E § 3.1.1 Legacy and extended advertising,
  // legacy advertising are rejected when this bit is set.
  bool extended_advertising_in_use_{false};

  // Legacy advertising state.
  LegacyAdvertiser legacy_advertiser_{};

  Address le_connecting_rpa_;
  // Extended advertising state.
  std::array<LeAdvertiser, 7> advertisers_{};

  struct Scanner {
    bool scan_enable;
    slots period;
    slots duration;
    bluetooth::hci::FilterDuplicates filter_duplicates;
    bluetooth::hci::OwnAddressType own_address_type;
    bluetooth::hci::LeScanningFilterPolicy scan_filter_policy;

    struct PhyParameters {
      bool enabled;
      bluetooth::hci::LeScanType scan_type;
      uint16_t scan_interval;
      uint16_t scan_window;
    };

    PhyParameters le_1m_phy;
    PhyParameters le_coded_phy;

    // Save information about the advertising PDU being scanned.
    bool connectable_scan_response;
    std::optional<AddressWithType> pending_scan_request{};

  std::array<LeAdvertiser, 7> advertisers_;
    // Time keeping
    std::optional<std::chrono::steady_clock::time_point> timeout;

  bluetooth::hci::OpCode le_scan_enable_{bluetooth::hci::OpCode::NONE};
  uint8_t le_scan_type_{};
    bool IsEnabled() const { return scan_enable; }
    void Disable() { scan_enable = false; }
  };

  // Legacy and extended scanning properties.
  // Legacy and extended scanning are disambiguated by the use
  // of legacy_advertising_in_use_ and extended_advertising_in_use_ flags.
  // Only one type of advertising may be used during a controller session.
  Scanner scanner_{};

  Address le_connecting_rpa_;
  uint16_t le_scan_interval_{};
  uint16_t le_scan_window_{};
  bluetooth::hci::LeScanningFilterPolicy le_scan_filter_policy_{};
  uint8_t le_scan_filter_duplicates_{};

  bluetooth::hci::OwnAddressType le_address_type_{};

  bool le_connect_{false};
@@ -827,8 +922,7 @@ class LinkLayerController {
  uint16_t le_connection_maximum_ce_length_{};
  bluetooth::hci::InitiatorFilterPolicy le_initiator_filter_policy_{};

  Address le_peer_address_{};
  uint8_t le_peer_address_type_{};
  AddressWithType le_peer_address_{};

  // Classic state
#ifdef ROOTCANAL_LMP
Loading