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

Commit 5674407d authored by Henri Chataing's avatar Henri Chataing Committed by Automerger Merge Worker
Browse files

Merge changes I454395fd,I8a0b4555 into main am: 739460bc

parents c8c98905 739460bc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1973,6 +1973,7 @@ ControllerProperties::ControllerProperties(
      supports_csr_vendor_command = config.vendor().csr();
    }
    if (config.vendor().has_android()) {
      supports_le_get_vendor_capabilities_command = config.vendor().android();
      supports_le_apcf_vendor_command = config.vendor().android();
    }
  }
+11 −3
Original line number Diff line number Diff line
@@ -155,9 +155,17 @@ struct ControllerProperties {
  // LE Periodic Advertiser List Size (Vol 4, Part E § 7.8.73).
  uint8_t le_periodic_advertiser_list_size{8};

  // Vendor Information.
  // Provide parameters returned by vendor specific commands.
  std::vector<uint8_t> le_vendor_capabilities{};
  // Android Vendor Capabilities.
  // https://source.android.com/docs/core/connect/bluetooth/hci_requirements#vendor-specific-capabilities
  uint8_t le_apcf_filter_list_size{8};
  uint8_t le_apcf_num_of_tracked_advertisers{8};
  uint8_t le_apcf_broadcaster_address_filter_list_size{8};
  uint8_t le_apcf_service_uuid_filter_list_size{8};
  uint8_t le_apcf_service_solicitation_uuid_filter_list_size{8};
  uint8_t le_apcf_local_name_filter_list_size{8};
  uint8_t le_apcf_manufacturer_data_filter_list_size{8};
  uint8_t le_apcf_service_data_filter_list_size{8};
  uint8_t le_apcf_ad_type_filter_list_size{8};

  bool SupportsLMPFeature(bluetooth::hci::LMPFeaturesPage0Bits bit) const {
    return (lmp_features[0] & static_cast<uint64_t>(bit)) != 0;
+19 −13
Original line number Diff line number Diff line
@@ -2805,19 +2805,25 @@ void DualModeController::LeGetVendorCapabilities(CommandView command) {
    return;
  }

  std::vector<uint8_t> return_parameters = {
      static_cast<uint8_t>(ErrorCode::SUCCESS)};
  return_parameters.insert(return_parameters.end(),
                           properties_.le_vendor_capabilities.begin(),
                           properties_.le_vendor_capabilities.end());
  // Ensure a minimal size for vendor capabilities.
  if (return_parameters.size() < 9) {
    return_parameters.resize(9);
  }

  send_event_(bluetooth::hci::CommandCompleteBuilder::Create(
      kNumCommandPackets, OpCode::LE_GET_VENDOR_CAPABILITIES,
      std::move(return_parameters)));
  DEBUG(id_, "<< LE Get Vendor Capabilities");

  bluetooth::hci::VendorCapabilities_V_0_98 vendor_capabilities;
  vendor_capabilities.total_scan_results_storage_ = 0;
  vendor_capabilities.max_irk_list_sz_ = 16;
  vendor_capabilities.filtering_support_ =
      properties_.supports_le_apcf_vendor_command;
  vendor_capabilities.max_filter_ = properties_.le_apcf_filter_list_size;
  vendor_capabilities.activity_energy_info_support_ = 0;
  vendor_capabilities.total_num_of_advt_tracked_ =
      properties_.le_apcf_num_of_tracked_advertisers;
  vendor_capabilities.extended_scan_support_ = 0;
  vendor_capabilities.debug_logging_supported_ = 0;
  vendor_capabilities.a2dp_source_offload_capability_mask_ = 0;
  vendor_capabilities.bluetooth_quality_report_support_ = 0;

  send_event_(bluetooth::hci::LeGetVendorCapabilitiesCompleteBuilder::Create(
      kNumCommandPackets, ErrorCode::SUCCESS,
      vendor_capabilities.SerializeToBytes()));
}

void DualModeController::LeBatchScan(CommandView command) {
+5 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "model/controller/controller_properties.h"
#include "model/controller/le_advertiser.h"
#include "model/controller/sco_connection.h"
#include "model/controller/vendor_commands/le_apcf.h"
#include "packets/hci_packets.h"
#include "packets/link_layer_packets.h"
#include "phy.h"
@@ -51,6 +52,7 @@ using ::bluetooth::hci::ErrorCode;
using ::bluetooth::hci::FilterAcceptListAddressType;
using ::bluetooth::hci::OpCode;
using ::bluetooth::hci::PageScanRepetitionMode;
using rootcanal::apcf::ApcfScanner;

// Create an address with type Public Device Address or Random Device Address.
AddressWithType PeerDeviceAddress(Address address,
@@ -1083,6 +1085,9 @@ class LinkLayerController {
  // Only one type of advertising may be used during a controller session.
  Scanner scanner_{};

  // APCF scanning state for Android vendor support.
  ApcfScanner apcf_scanner_{};

  struct Initiator {
    bool connect_enable;
    bluetooth::hci::InitiatorFilterPolicy initiator_filter_policy;
+299 −20
Original line number Diff line number Diff line
@@ -16,74 +16,353 @@
 * limitations under the License.
 */

#include <algorithm>
#include <cstdint>

#include "log.h"
#include "model/controller/link_layer_controller.h"
#include "packets/hci_packets.h"

#pragma GCC diagnostic ignored "-Wunused-parameter"

namespace rootcanal::apcf {

bool ApcfScanner::HasFilterIndex(uint8_t apcf_filter_index) const {
  return std::any_of(std::begin(filters), std::end(filters), [&](auto it) {
    return it.filter_index == apcf_filter_index;
  });
}

void ApcfScanner::ClearFilterIndex(uint8_t apcf_filter_index) {
  std::remove_if(std::begin(broadcaster_address_filters),
                 std::end(broadcaster_address_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(service_uuid_filters),
                 std::end(service_uuid_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(service_solicitation_uuid_filters),
                 std::end(service_solicitation_uuid_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(local_name_filters), std::end(local_name_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(manufacturer_data_filters),
                 std::end(manufacturer_data_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(service_data_filters),
                 std::end(service_data_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
  std::remove_if(std::begin(ad_type_filters), std::end(ad_type_filters),
                 [&](auto it) { return it.filter_index == apcf_filter_index; });
}

template <typename T>
ErrorCode ApcfScanner::UpdateFilterList(std::vector<T>& filter_list,
                                        size_t max_filter_list_size,
                                        bluetooth::hci::ApcfAction action,
                                        T filter) {
  if (!HasFilterIndex(filter.filter_index)) {
    return ErrorCode::UNKNOWN_CONNECTION;
  }

  switch (action) {
    case ApcfAction::ADD: {
      if (filter_list.size() == max_filter_list_size) {
        return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
      }

      filter_list.emplace_back(std::move(filter));
      return ErrorCode::SUCCESS;
    }
    case ApcfAction::DELETE: {
      // Delete will delete the specified data in the specified filter.
      std::remove_if(std::begin(filter_list), std::end(filter_list),
                     [&](auto it) { return it == filter; });
      return ErrorCode::SUCCESS;
    }
    case ApcfAction::CLEAR: {
      // Clear will clear all data in the specified filter.
      std::remove_if(
          std::begin(filter_list), std::end(filter_list),
          [&](auto it) { return it.filter_index == filter.filter_index; });
      return ErrorCode::SUCCESS;
    }
    default:
      break;
  }

  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
}

bool operator==(BroadcasterAddressFilter const& lhs,
                BroadcasterAddressFilter const& rhs) {
  return lhs.filter_index == rhs.filter_index &&
         lhs.broadcaster_address == rhs.broadcaster_address &&
         lhs.application_address_type == rhs.application_address_type;
}

bool operator==(GapDataFilter const& lhs, GapDataFilter const& rhs) {
  return lhs.filter_index == rhs.filter_index && lhs.gap_data == rhs.gap_data &&
         lhs.gap_data_mask == rhs.gap_data_mask;
}

bool operator==(AdTypeFilter const& lhs, AdTypeFilter const& rhs) {
  return lhs.filter_index == rhs.filter_index && lhs.ad_type == rhs.ad_type &&
         lhs.ad_data == rhs.ad_data && lhs.ad_data_mask == rhs.ad_data_mask;
}

}  // namespace rootcanal::apcf

namespace rootcanal {

using bluetooth::hci::ApcfAction;

ErrorCode LinkLayerController::LeApcfEnable(bool apcf_enable) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  apcf_scanner_.enable = apcf_enable;
  return ErrorCode::SUCCESS;
}

ErrorCode LinkLayerController::LeApcfSetFilteringParameters(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    uint16_t apcf_feature_selection, uint16_t apcf_list_logic_type,
    uint8_t apcf_filter_logic_type, uint8_t rssi_high_thresh,
    bluetooth::hci::DeliveryMode delivery_mode, uint16_t onfound_timeout,
    uint8_t onfound_timeout_cnt, uint8_t rssi_low_thresh,
    uint16_t onlost_timeout, uint16_t num_of_tracking_entries,
    uint8_t* apcf_available_spaces) {
  *apcf_available_spaces =
      properties_.le_apcf_filter_list_size - apcf_scanner_.filters.size();

  switch (apcf_action) {
    case ApcfAction::ADD: {
      if (apcf_scanner_.HasFilterIndex(apcf_filter_index)) {
        INFO(id_, "apcf filter index {} already configured", apcf_filter_index);
        return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
      }

      if (*apcf_available_spaces == 0) {
        INFO(id_, "reached max number of apcf filters");
        return ErrorCode::MEMORY_CAPACITY_EXCEEDED;
      }

      apcf_scanner_.filters.push_back(rootcanal::apcf::Filter{
          .filter_index = apcf_filter_index,
          .feature_selection = apcf_feature_selection,
          .list_logic_type = apcf_list_logic_type,
          .filter_logic_type = apcf_filter_logic_type,
          .rssi_high_thresh = rssi_high_thresh,
          .delivery_mode = delivery_mode,
          .onfound_timeout = onfound_timeout,
          .onfound_timeout_cnt = onfound_timeout_cnt,
          .rssi_low_thresh = rssi_low_thresh,
          .onlost_timeout = onlost_timeout,
          .num_of_tracking_entries = num_of_tracking_entries,
      });

      *apcf_available_spaces -= 1;
      return ErrorCode::SUCCESS;
    }

    case ApcfAction::DELETE: {
      if (!apcf_scanner_.HasFilterIndex(apcf_filter_index)) {
        INFO(id_, "apcf filter index {} is not configured", apcf_filter_index);
        return ErrorCode::UNKNOWN_CONNECTION;
      }

      std::remove_if(
          std::begin(apcf_scanner_.filters), std::end(apcf_scanner_.filters),
          [&](auto it) { return it.filter_index == apcf_filter_index; });

      apcf_scanner_.ClearFilterIndex(apcf_filter_index);
      *apcf_available_spaces += 1;
      return ErrorCode::SUCCESS;
    }

    case ApcfAction::CLEAR: {
      if (!apcf_scanner_.HasFilterIndex(apcf_filter_index)) {
        INFO(id_, "apcf filter index {} is not configured", apcf_filter_index);
        return ErrorCode::UNKNOWN_CONNECTION;
      }

      apcf_scanner_.ClearFilterIndex(apcf_filter_index);
      return ErrorCode::SUCCESS;
    }

    default:
      INFO(id_, "unknown apcf action {}", apcf_action);
      break;
  }

  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
}

ErrorCode LinkLayerController::LeApcfBroadcasterAddress(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    bluetooth::hci::Address apcf_broadcaster_address,
    bluetooth::hci::ApcfApplicationAddressType apcf_application_address_type,
    uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.broadcaster_address_filters,
      properties_.le_apcf_broadcaster_address_filter_list_size, apcf_action,
      rootcanal::apcf::BroadcasterAddressFilter{
          .filter_index = apcf_filter_index,
          .broadcaster_address = apcf_broadcaster_address,
          .application_address_type = apcf_application_address_type,
      });

  *apcf_available_spaces =
      properties_.le_apcf_broadcaster_address_filter_list_size -
      apcf_scanner_.broadcaster_address_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfServiceUuid(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> acpf_uuid_data, uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> apcf_uuid_data, uint8_t* apcf_available_spaces) {
  size_t uuid_data_size = apcf_uuid_data.size() / 2;
  std::vector<uint8_t> uuid_data(std::begin(apcf_uuid_data),
                                 std::begin(apcf_uuid_data) + uuid_data_size);
  std::vector<uint8_t> uuid_data_mask(
      std::begin(apcf_uuid_data) + uuid_data_size, std::end(apcf_uuid_data));

  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.service_uuid_filters,
      properties_.le_apcf_service_uuid_filter_list_size, apcf_action,
      rootcanal::apcf::GapDataFilter{
          .filter_index = apcf_filter_index,
          .gap_data = uuid_data,
          .gap_data_mask = uuid_data_mask,
      });

  *apcf_available_spaces = properties_.le_apcf_service_uuid_filter_list_size -
                           apcf_scanner_.service_uuid_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfServiceSolicitationUuid(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> acpf_uuid_data, uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> apcf_uuid_data, uint8_t* apcf_available_spaces) {
  size_t uuid_data_size = apcf_uuid_data.size() / 2;
  std::vector<uint8_t> uuid_data(std::begin(apcf_uuid_data),
                                 std::begin(apcf_uuid_data) + uuid_data_size);
  std::vector<uint8_t> uuid_data_mask(
      std::begin(apcf_uuid_data) + uuid_data_size, std::end(apcf_uuid_data));

  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.service_solicitation_uuid_filters,
      properties_.le_apcf_service_solicitation_uuid_filter_list_size,
      apcf_action,
      rootcanal::apcf::GapDataFilter{
          .filter_index = apcf_filter_index,
          .gap_data = uuid_data,
          .gap_data_mask = uuid_data_mask,
      });

  *apcf_available_spaces =
      properties_.le_apcf_service_solicitation_uuid_filter_list_size -
      apcf_scanner_.service_solicitation_uuid_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfLocalName(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> apcf_local_name, uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  size_t local_name_size = apcf_local_name.size() / 2;
  std::vector<uint8_t> local_name(
      std::begin(apcf_local_name),
      std::begin(apcf_local_name) + local_name_size);
  std::vector<uint8_t> local_name_mask(
      std::begin(apcf_local_name) + local_name_size, std::end(apcf_local_name));

  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.local_name_filters,
      properties_.le_apcf_local_name_filter_list_size, apcf_action,
      rootcanal::apcf::GapDataFilter{
          .filter_index = apcf_filter_index,
          .gap_data = local_name,
          .gap_data_mask = local_name_mask,
      });

  *apcf_available_spaces = properties_.le_apcf_local_name_filter_list_size -
                           apcf_scanner_.local_name_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfManufacturerData(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> apcf_manufacturer_data,
    uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  size_t manufacturer_data_size = apcf_manufacturer_data.size() / 2;
  std::vector<uint8_t> manufacturer_data(
      std::begin(apcf_manufacturer_data),
      std::begin(apcf_manufacturer_data) + manufacturer_data_size);
  std::vector<uint8_t> manufacturer_data_mask(
      std::begin(apcf_manufacturer_data) + manufacturer_data_size,
      std::end(apcf_manufacturer_data));

  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.manufacturer_data_filters,
      properties_.le_apcf_manufacturer_data_filter_list_size, apcf_action,
      rootcanal::apcf::GapDataFilter{
          .filter_index = apcf_filter_index,
          .gap_data = manufacturer_data,
          .gap_data_mask = manufacturer_data_mask,
      });

  *apcf_available_spaces =
      properties_.le_apcf_manufacturer_data_filter_list_size -
      apcf_scanner_.manufacturer_data_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfServiceData(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    ApcfAction apcf_action, uint8_t apcf_filter_index,
    std::vector<uint8_t> apcf_service_data, uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  size_t service_data_size = apcf_service_data.size() / 2;
  std::vector<uint8_t> service_data(
      std::begin(apcf_service_data),
      std::begin(apcf_service_data) + service_data_size);
  std::vector<uint8_t> service_data_mask(
      std::begin(apcf_service_data) + service_data_size,
      std::end(apcf_service_data));

  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.service_data_filters,
      properties_.le_apcf_service_data_filter_list_size, apcf_action,
      rootcanal::apcf::GapDataFilter{
          .filter_index = apcf_filter_index,
          .gap_data = service_data,
          .gap_data_mask = service_data_mask,
      });

  *apcf_available_spaces = properties_.le_apcf_service_data_filter_list_size -
                           apcf_scanner_.service_data_filters.size();

  return status;
}

ErrorCode LinkLayerController::LeApcfAdTypeFilter(
    bluetooth::hci::ApcfAction apcf_action, uint8_t apcf_filter_index,
    uint8_t ad_type, std::vector<uint8_t> apcf_ad_data,
    std::vector<uint8_t> apcf_ad_data_mask, uint8_t* apcf_available_spaces) {
  return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
    ApcfAction apcf_action, uint8_t apcf_filter_index, uint8_t apcf_ad_type,
    std::vector<uint8_t> apcf_ad_data, std::vector<uint8_t> apcf_ad_data_mask,
    uint8_t* apcf_available_spaces) {
  ErrorCode status = apcf_scanner_.UpdateFilterList(
      apcf_scanner_.ad_type_filters,
      properties_.le_apcf_ad_type_filter_list_size, apcf_action,
      rootcanal::apcf::AdTypeFilter{
          .filter_index = apcf_filter_index,
          .ad_type = apcf_ad_type,
          .ad_data = std::move(apcf_ad_data),
          .ad_data_mask = std::move(apcf_ad_data_mask),
      });

  *apcf_available_spaces = properties_.le_apcf_ad_type_filter_list_size -
                           apcf_scanner_.ad_type_filters.size();

  return status;
}

}  // namespace rootcanal
Loading