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

Commit 946ede16 authored by Chris Manton's avatar Chris Manton
Browse files

Inquiry and page scan common module

Bug: 142061208
Test: Builds successfully
Change-Id: I0ca7afb996490fff71030bf949ea9647924fd458
parent 45d54000
Loading
Loading
Loading
Loading
+206 −0
Original line number Original line 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 "neighbor/scan.h"
#include <memory>
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace neighbor {

struct ScanModule::impl {
  impl(ScanModule& module);

  void SetInquiryScan(bool enabled);
  bool IsInquiryEnabled() const;

  void SetPageScan(bool enabled);
  bool IsPageEnabled() const;

  void Start();
  void Stop();

 private:
  ScanModule& module_;

  bool inquiry_scan_enabled_;
  bool page_scan_enabled_;

  void WriteScanEnable();
  void ReadScanEnable(hci::ScanEnable);

  void OnCommandComplete(hci::CommandCompleteView status);

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

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

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()) {
      case hci::OpCode::READ_SCAN_ENABLE: {
        auto packet = hci::ReadScanEnableCompleteView::Create(view);
        ASSERT(packet.IsValid());
        ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
        ReadScanEnable(packet.GetScanEnable());
      } break;

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

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

void neighbor::ScanModule::impl::WriteScanEnable() {
  hci::ScanEnable scan_enable;

  if (inquiry_scan_enabled_ && !page_scan_enabled_) {
    scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
  } else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
    scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
  } else if (inquiry_scan_enabled_ && page_scan_enabled_) {
    scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
  } else {
    scan_enable = hci::ScanEnable::NO_SCANS;
  }

  {
    std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable);
    hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
                               handler_);
  }

  {
    std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
    hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
                               handler_);
  }
}

void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) {
  switch (scan_enable) {
    case hci::ScanEnable::INQUIRY_SCAN_ONLY:
      inquiry_scan_enabled_ = true;
      page_scan_enabled_ = false;
      break;

    case hci::ScanEnable::PAGE_SCAN_ONLY:
      inquiry_scan_enabled_ = false;
      page_scan_enabled_ = true;
      break;

    case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN:
      inquiry_scan_enabled_ = true;
      page_scan_enabled_ = true;
      break;

    default:
      inquiry_scan_enabled_ = false;
      page_scan_enabled_ = false;
      break;
  }
}

void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) {
  inquiry_scan_enabled_ = enabled;
  WriteScanEnable();
}

void neighbor::ScanModule::impl::SetPageScan(bool enabled) {
  page_scan_enabled_ = enabled;
  WriteScanEnable();
}

bool neighbor::ScanModule::impl::IsInquiryEnabled() const {
  return inquiry_scan_enabled_;
}

bool neighbor::ScanModule::impl::IsPageEnabled() const {
  return page_scan_enabled_;
}

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

  std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
  hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
                             handler_);
}

void neighbor::ScanModule::impl::Stop() {
  LOG_DEBUG("inquiry scan enabled:%d page scan enabled:%d", inquiry_scan_enabled_, page_scan_enabled_);
}

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

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

void neighbor::ScanModule::SetInquiryScan() {
  pimpl_->SetInquiryScan(true);
}

void neighbor::ScanModule::ClearInquiryScan() {
  pimpl_->SetInquiryScan(false);
}

void neighbor::ScanModule::SetPageScan() {
  pimpl_->SetPageScan(true);
}

void neighbor::ScanModule::ClearPageScan() {
  pimpl_->SetPageScan(false);
}

bool neighbor::ScanModule::IsInquiryEnabled() const {
  return pimpl_->IsInquiryEnabled();
}

bool neighbor::ScanModule::IsPageEnabled() const {
  return pimpl_->IsPageEnabled();
}

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

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

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

}  // namespace neighbor
}  // namespace bluetooth
+53 −0
Original line number Original line 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 ScanModule : public bluetooth::Module {
 public:
  ScanModule();
  ~ScanModule();

  void SetInquiryScan();
  void ClearInquiryScan();
  bool IsInquiryEnabled() const;

  void SetPageScan();
  void ClearPageScan();
  bool IsPageEnabled() const;

  static const ModuleFactory Factory;

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

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

  DISALLOW_COPY_AND_ASSIGN(ScanModule);
};

}  // namespace neighbor
}  // namespace bluetooth