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

Commit 78722a2f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ib4c81ba3,I79bead5d

* changes:
  Add discoverability module
  Add page scan module
parents 79cb0df5 6891ecb7
Loading
Loading
Loading
Loading
+193 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "bt_gd_neigh"

#include <memory>

#include "common/bind.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "neighbor/discoverability.h"
#include "neighbor/scan.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace neighbor {

static constexpr uint8_t kGeneralInquiryAccessCode = 0x33;
static constexpr uint8_t kLimitedInquiryAccessCode = 0x00;

struct DiscoverabilityModule::impl {
  void StartDiscoverability(std::vector<hci::Lap>& laps);
  void StopDiscoverability();

  bool IsGeneralDiscoverabilityEnabled() const;
  bool IsLimitedDiscoverabilityEnabled() const;

  void Start();

  impl(DiscoverabilityModule& discoverability_module);

 private:
  uint8_t num_supported_iac_;
  std::vector<hci::Lap> laps_;

  void OnCommandComplete(hci::CommandCompleteView status);

  hci::HciLayer* hci_layer_;
  neighbor::ScanModule* scan_module_;
  os::Handler* handler_;

  DiscoverabilityModule& module_;
  void Dump() const;
};

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

neighbor::DiscoverabilityModule::impl::impl(neighbor::DiscoverabilityModule& module) : module_(module) {}

void neighbor::DiscoverabilityModule::impl::OnCommandComplete(hci::CommandCompleteView status) {
  switch (status.GetCommandOpCode()) {
    case hci::OpCode::READ_CURRENT_IAC_LAP: {
      auto packet = hci::ReadCurrentIacLapCompleteView::Create(status);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
      laps_ = packet.GetLapsToRead();
    } break;

    case hci::OpCode::WRITE_CURRENT_IAC_LAP: {
      auto packet = hci::WriteCurrentIacLapCompleteView::Create(status);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
    } break;

    case hci::OpCode::READ_NUMBER_OF_SUPPORTED_IAC: {
      auto packet = hci::ReadNumberOfSupportedIacCompleteView::Create(status);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
      num_supported_iac_ = packet.GetNumSupportIac();
    } break;
    default:
      LOG_WARN("Unhandled command:%s", hci::OpCodeText(status.GetCommandOpCode()).c_str());
      break;
  }
}

void neighbor::DiscoverabilityModule::impl::StartDiscoverability(std::vector<hci::Lap>& laps) {
  ASSERT(laps.size() <= num_supported_iac_);
  hci_layer_->EnqueueCommand(hci::WriteCurrentIacLapBuilder::Create(laps),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  hci_layer_->EnqueueCommand(hci::ReadCurrentIacLapBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  scan_module_->SetInquiryScan();
}

void neighbor::DiscoverabilityModule::impl::StopDiscoverability() {
  scan_module_->ClearInquiryScan();
}

bool neighbor::DiscoverabilityModule::impl::IsGeneralDiscoverabilityEnabled() const {
  return scan_module_->IsInquiryEnabled() && laps_.size() == 1;
}

bool neighbor::DiscoverabilityModule::impl::IsLimitedDiscoverabilityEnabled() const {
  return scan_module_->IsInquiryEnabled() && laps_.size() == 2;
}

void neighbor::DiscoverabilityModule::impl::Start() {
  hci_layer_ = module_.GetDependency<hci::HciLayer>();
  scan_module_ = module_.GetDependency<neighbor::ScanModule>();
  handler_ = module_.GetHandler();

  hci_layer_->EnqueueCommand(hci::ReadCurrentIacLapBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadNumberOfSupportedIacBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  LOG_DEBUG("Started discoverability module");
}

void neighbor::DiscoverabilityModule::impl::Dump() const {
  LOG_DEBUG("Number of supported iacs:%hhd", num_supported_iac_);
  LOG_DEBUG("Number of current iacs:%zd", laps_.size());
  for (auto it : laps_) {
    LOG_DEBUG("  discoverability lap:%x", it.lap_);
  }
}

neighbor::DiscoverabilityModule::DiscoverabilityModule() : pimpl_(std::make_unique<impl>(*this)) {}

neighbor::DiscoverabilityModule::~DiscoverabilityModule() {
  pimpl_.reset();
}

void neighbor::DiscoverabilityModule::StartGeneralDiscoverability() {
  std::vector<hci::Lap> laps;
  {
    hci::Lap lap;
    lap.lap_ = kGeneralInquiryAccessCode;
    laps.push_back(lap);
  }
  pimpl_->StartDiscoverability(laps);
}

void neighbor::DiscoverabilityModule::StartLimitedDiscoverability() {
  std::vector<hci::Lap> laps;
  {
    hci::Lap lap;
    lap.lap_ = kGeneralInquiryAccessCode;
    laps.push_back(lap);
  }

  {
    hci::Lap lap;
    lap.lap_ = kLimitedInquiryAccessCode;
    laps.push_back(lap);
  }
  pimpl_->StartDiscoverability(laps);
}

void neighbor::DiscoverabilityModule::StopDiscoverability() {
  pimpl_->StopDiscoverability();
}

bool neighbor::DiscoverabilityModule::IsGeneralDiscoverabilityEnabled() const {
  return pimpl_->IsGeneralDiscoverabilityEnabled();
}

bool neighbor::DiscoverabilityModule::IsLimitedDiscoverabilityEnabled() const {
  return pimpl_->IsLimitedDiscoverabilityEnabled();
}

/**
 * Module stuff
 */
void neighbor::DiscoverabilityModule::ListDependencies(ModuleList* list) {
  list->add<hci::HciLayer>();
  list->add<neighbor::ScanModule>();
}

void neighbor::DiscoverabilityModule::Start() {
  pimpl_->Start();
}

void neighbor::DiscoverabilityModule::Stop() {}

}  // namespace neighbor
}  // namespace bluetooth
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <memory>

#include "module.h"

namespace bluetooth {
namespace neighbor {

class DiscoverabilityModule : public bluetooth::Module {
 public:
  void StartGeneralDiscoverability();
  void StartLimitedDiscoverability();
  void StopDiscoverability();

  bool IsGeneralDiscoverabilityEnabled() const;
  bool IsLimitedDiscoverabilityEnabled() const;

  static const ModuleFactory Factory;

  DiscoverabilityModule();
  ~DiscoverabilityModule();

 protected:
  void ListDependencies(ModuleList* list) override;
  void Start() override;
  void Stop() override;

 private:
  struct impl;
  std::unique_ptr<impl> pimpl_;

  DISALLOW_COPY_AND_ASSIGN(DiscoverabilityModule);
};

}  // namespace neighbor
}  // namespace bluetooth
+206 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "bt_gd_neigh"

#include <memory>

#include "common/bind.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "neighbor/page.h"
#include "neighbor/scan_parameters.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace neighbor {

struct PageModule::impl {
  void SetScanActivity(ScanParameters params);
  ScanParameters GetScanActivity() const;

  void SetScanType(hci::PageScanType type);

  void SetTimeout(PageTimeout timeout);

  void Start();
  void Stop();

  impl(PageModule& page_module);

 private:
  PageModule& module_;

  ScanParameters scan_parameters_;
  hci::PageScanType scan_type_;
  PageTimeout timeout_;

  void OnCommandComplete(hci::CommandCompleteView status);

  hci::HciLayer* hci_layer_;
  os::Handler* handler_;
};

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

neighbor::PageModule::impl::impl(neighbor::PageModule& module) : module_(module) {}

void neighbor::PageModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
  switch (view.GetCommandOpCode()) {
    case hci::OpCode::WRITE_PAGE_SCAN_ACTIVITY: {
      auto packet = hci::WritePageScanActivityCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
    } break;

    case hci::OpCode::READ_PAGE_SCAN_ACTIVITY: {
      auto packet = hci::ReadPageScanActivityCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
      scan_parameters_.interval = packet.GetPageScanInterval();
      scan_parameters_.window = packet.GetPageScanWindow();
    } break;

    case hci::OpCode::WRITE_PAGE_SCAN_TYPE: {
      auto packet = hci::WritePageScanTypeCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
    } break;

    case hci::OpCode::READ_PAGE_SCAN_TYPE: {
      auto packet = hci::ReadPageScanTypeCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
      scan_type_ = packet.GetPageScanType();
    } break;

    case hci::OpCode::WRITE_PAGE_TIMEOUT: {
      auto packet = hci::WritePageTimeoutCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
    } break;

    case hci::OpCode::READ_PAGE_TIMEOUT: {
      auto packet = hci::ReadPageTimeoutCompleteView::Create(view);
      ASSERT(packet.IsValid());
      ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
      timeout_ = packet.GetPageTimeout();
    } break;

    default:
      LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
      break;
  }
}

void neighbor::PageModule::impl::Start() {
  hci_layer_ = module_.GetDependency<hci::HciLayer>();
  handler_ = module_.GetHandler();

  hci_layer_->EnqueueCommand(hci::ReadPageScanActivityBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadPageScanTypeBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadPageTimeoutBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
}

void neighbor::PageModule::impl::Stop() {
  LOG_DEBUG("Page scan interval:%hd window:%hd", scan_parameters_.interval, scan_parameters_.window);
  LOG_DEBUG("Page scan_type:%s", hci::PageScanTypeText(scan_type_).c_str());
}

void neighbor::PageModule::impl::SetScanActivity(ScanParameters params) {
  hci_layer_->EnqueueCommand(hci::WritePageScanActivityBuilder::Create(params.interval, params.window),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadPageScanActivityBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  LOG_DEBUG("Set page scan activity interval:0x%x/%.02fms window:0x%x/%.02fms", params.interval,
            ScanIntervalTimeMs(params.interval), params.window, ScanWindowTimeMs(params.window));
}

ScanParameters neighbor::PageModule::impl::GetScanActivity() const {
  return scan_parameters_;
}

void neighbor::PageModule::impl::SetScanType(hci::PageScanType scan_type) {
  hci_layer_->EnqueueCommand(hci::WritePageScanTypeBuilder::Create(scan_type),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadPageScanTypeBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  LOG_DEBUG("Set page scan type:%s", hci::PageScanTypeText(scan_type).c_str());
}

void neighbor::PageModule::impl::SetTimeout(PageTimeout timeout) {
  hci_layer_->EnqueueCommand(hci::WritePageTimeoutBuilder::Create(timeout),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);

  hci_layer_->EnqueueCommand(hci::ReadPageTimeoutBuilder::Create(),
                             common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
  LOG_DEBUG("Set page scan timeout:0x%x/%.02fms", timeout, PageTimeoutMs(timeout));
}

/**
 * General API here
 */
neighbor::PageModule::PageModule() : pimpl_(std::make_unique<impl>(*this)) {}

neighbor::PageModule::~PageModule() {
  pimpl_.reset();
}

void neighbor::PageModule::SetScanActivity(ScanParameters params) {
  pimpl_->SetScanActivity(params);
}

ScanParameters neighbor::PageModule::GetScanActivity() const {
  return pimpl_->GetScanActivity();
}

void neighbor::PageModule::SetInterlacedScan() {
  pimpl_->SetScanType(hci::PageScanType::INTERLACED);
}

void neighbor::PageModule::SetStandardScan() {
  pimpl_->SetScanType(hci::PageScanType::STANDARD);
}

void neighbor::PageModule::SetTimeout(PageTimeout timeout) {
  pimpl_->SetTimeout(timeout);
}

/**
 * Module methods here
 */
void neighbor::PageModule::ListDependencies(ModuleList* list) {
  list->add<hci::HciLayer>();
}

void neighbor::PageModule::Start() {
  pimpl_->Start();
}

void neighbor::PageModule::Stop() {
  pimpl_->Stop();
}

}  // namespace neighbor
}  // namespace bluetooth
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <memory>

#include "hci/hci_packets.h"
#include "module.h"
#include "neighbor/scan_parameters.h"

namespace bluetooth {
namespace neighbor {

using PageTimeout = uint16_t;  // Range = 0x0001 to 0xffff, Time N * 0.625ms

inline double PageTimeoutMs(PageTimeout timeout) {
  return kTimeTickMs * timeout;
}

class PageModule : public bluetooth::Module {
 public:
  void SetScanActivity(ScanParameters params);
  ScanParameters GetScanActivity() const;

  void SetInterlacedScan();
  void SetStandardScan();

  void SetTimeout(PageTimeout timeout);

  static const ModuleFactory Factory;

  PageModule();
  ~PageModule();

 protected:
  void ListDependencies(ModuleList* list) override;
  void Start() override;
  void Stop() override;

 private:
  struct impl;
  std::unique_ptr<impl> pimpl_;

  DISALLOW_COPY_AND_ASSIGN(PageModule);
};

}  // namespace neighbor
}  // namespace bluetooth
+18 −18
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ neighbor::ScanModule::impl::impl(neighbor::ScanModule& module)
    : module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {}

void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
  switch veiwstatus.GetCommandOpCode()) {
  switch (view.GetCommandOpCode()) {
    case hci::OpCode::READ_SCAN_ENABLE: {
      auto packet = hci::ReadScanEnableCompleteView::Create(view);
      ASSERT(packet.IsValid());