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

Commit 73addef9 authored by Jayden Kim's avatar Jayden Kim
Browse files

Adds RF path loss compensation for LE advertise and scan

- tx path loss compensation for tx power in advertise configuration
- rx path loss compensation for rssi in scan results

Bug: 277676657
Test: device test
Tag: #feature
Change-Id: I5b4aa209c9a413cdc4ccb92b6e146401b6a2b86c
parent 70bee993
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <mutex>

#include "common/init_flags.h"
#include "common/strings.h"
#include "hci/acl_manager.h"
#include "hci/controller.h"
#include "hci/hci_layer.h"
@@ -36,6 +37,13 @@ namespace hci {
const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });
constexpr int kIdLocal = 0xff;  // Id for advertiser not register from Java layer
constexpr uint16_t kLenOfFlags = 0x03;
constexpr int64_t kLeAdvertisingTxPowerMin = -127;
constexpr int64_t kLeAdvertisingTxPowerMax = 20;
constexpr int64_t kLeTxPathLossCompMin = -128;
constexpr int64_t kLeTxPathLossCompMax = 127;

// system properties
const std::string kLeTxPathLossCompProperty = "bluetooth.hardware.radio.le_tx_path_loss_comp_db";

enum class AdvertisingApiType {
  LEGACY = 1,
@@ -149,6 +157,40 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
    for (size_t i = 0; i < enabled_sets_.size(); i++) {
      enabled_sets_[i].advertising_handle_ = kInvalidHandle;
    }
    le_tx_path_loss_comp_ = get_tx_path_loss_compensation();
  }

  int8_t get_tx_path_loss_compensation() {
    int8_t compensation = 0;
    auto compensation_prop = os::GetSystemProperty(kLeTxPathLossCompProperty);
    if (compensation_prop) {
      auto compensation_number = common::Int64FromString(compensation_prop.value());
      if (compensation_number) {
        int64_t number = compensation_number.value();
        if (number < kLeTxPathLossCompMin || number > kLeTxPathLossCompMax) {
          LOG_ERROR("Invalid number for tx path loss compensation: %" PRId64, number);
        } else {
          compensation = number;
        }
      }
    }
    LOG_INFO("Tx path loss compensation: %d", compensation);
    return compensation;
  }

  int8_t get_tx_power_after_calibration(int8_t tx_power) {
    if (le_tx_path_loss_comp_ == 0) {
      return tx_power;
    }
    int8_t calibrated_tx_power = tx_power;
    int64_t number = tx_power + le_tx_path_loss_comp_;
    if (number < kLeAdvertisingTxPowerMin || number > kLeAdvertisingTxPowerMax) {
      LOG_ERROR("Invalid number for calibrated tx power: %" PRId64, number);
    } else {
      calibrated_tx_power = number;
    }
    LOG_INFO("tx_power: %d, calibrated_tx_power: %d", tx_power, calibrated_tx_power);
    return calibrated_tx_power;
  }

  size_t GetNumberOfAdvertisingInstances() const {
@@ -630,6 +672,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
  }

  void set_parameters(AdvertiserId advertiser_id, AdvertisingConfig config) {
    config.tx_power = get_tx_power_after_calibration(static_cast<int8_t>(config.tx_power));
    advertising_sets_[advertiser_id].connectable = config.connectable;
    advertising_sets_[advertiser_id].discoverable = config.discoverable;
    advertising_sets_[advertiser_id].tx_power = config.tx_power;
@@ -1251,6 +1294,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
  hci::Controller* controller_;
  uint16_t le_maximum_advertising_data_length_;
  int8_t le_physical_channel_tx_power_ = 0;
  int8_t le_tx_path_loss_comp_ = 0;
  hci::LeAdvertisingInterface* le_advertising_interface_;
  std::map<AdvertiserId, Advertiser> advertising_sets_;
  hci::LeAddressManager* le_address_manager_;
+44 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "module.h"
#include "os/handler.h"
#include "os/log.h"
#include "os/system_properties.h"
#include "storage/storage_module.h"

namespace bluetooth {
@@ -36,6 +37,11 @@ namespace hci {

constexpr uint16_t kLeScanWindowMin = 0x0004;
constexpr uint16_t kLeScanWindowMax = 0x4000;
constexpr int64_t kLeScanRssiMin = -127;
constexpr int64_t kLeScanRssiMax = 20;
constexpr int64_t kLeScanRssiUnknown = 127;
constexpr int64_t kLeRxPathLossCompMin = -128;
constexpr int64_t kLeRxPathLossCompMax = 127;
constexpr uint16_t kDefaultLeExtendedScanWindow = 4800;
constexpr uint16_t kLeExtendedScanWindowMax = 0xFFFF;
constexpr uint16_t kLeScanIntervalMin = 0x0004;
@@ -49,6 +55,9 @@ constexpr uint8_t kScanResponseBit = 3;
constexpr uint8_t kLegacyBit = 4;
constexpr uint8_t kDataStatusBits = 5;

// system properties
const std::string kLeRxPathLossCompProperty = "bluetooth.hardware.radio.le_rx_path_loss_comp_db";

const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });

enum class ScanApiType {
@@ -212,6 +221,7 @@ struct LeScanningManager::impl : public LeAddressManagerCallback {
    }
    batch_scan_config_.current_state = BatchScanState::DISABLED_STATE;
    batch_scan_config_.ref_value = kInvalidScannerId;
    le_rx_path_loss_comp_ = get_rx_path_loss_compensation();
  }

  void stop() {
@@ -277,6 +287,38 @@ struct LeScanningManager::impl : public LeAddressManagerCallback {
    bool truncated{false};
  };

  int8_t get_rx_path_loss_compensation() {
    int8_t compensation = 0;
    auto compensation_prop = os::GetSystemProperty(kLeRxPathLossCompProperty);
    if (compensation_prop) {
      auto compensation_number = common::Int64FromString(compensation_prop.value());
      if (compensation_number) {
        int64_t number = compensation_number.value();
        if (number < kLeRxPathLossCompMin || number > kLeRxPathLossCompMax) {
          LOG_ERROR("Invalid number for rx path loss compensation: %" PRId64, number);
        } else {
          compensation = number;
        }
      }
    }
    LOG_INFO("Rx path loss compensation: %d", compensation);
    return compensation;
  }

  int8_t get_rssi_after_calibration(int8_t rssi) {
    if (le_rx_path_loss_comp_ == 0 || rssi == kLeScanRssiUnknown) {
      return rssi;
    }
    int8_t calibrated_rssi = rssi;
    int64_t number = rssi + le_rx_path_loss_comp_;
    if (number < kLeScanRssiMin || number > kLeScanRssiMax) {
      LOG_ERROR("Invalid number for calibrated rssi: %" PRId64, number);
    } else {
      calibrated_rssi = number;
    }
    return calibrated_rssi;
  }

  uint16_t transform_to_extended_event_type(ExtendedEventTypeOptions o) {
    return (o.connectable ? 0x0001 << 0 : 0) | (o.scannable ? 0x0001 << 1 : 0) |
           (o.directed ? 0x0001 << 2 : 0) | (o.scan_response ? 0x0001 << 3 : 0) |
@@ -414,7 +456,7 @@ struct LeScanningManager::impl : public LeAddressManagerCallback {
          secondary_phy,
          advertising_sid,
          tx_power,
          rssi,
          get_rssi_after_calibration(rssi),
          periodic_advertising_interval,
          complete_advertising_data.value());
    }
@@ -1584,6 +1626,7 @@ struct LeScanningManager::impl : public LeAddressManagerCallback {
  std::map<ScannerId, std::vector<uint8_t>> batch_scan_result_cache_;
  std::unordered_map<uint8_t, ScannerId> tracker_id_map_;
  uint16_t total_num_of_advt_tracked_ = 0x00;
  int8_t le_rx_path_loss_comp_ = 0;

  static void check_status(CommandCompleteView view) {
    switch (view.GetCommandOpCode()) {
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#pragma once

#include <inttypes.h>

#include <cstdlib>

#ifndef LOG_TAG