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

Commit d8a41832 authored by Chris Manton's avatar Chris Manton
Browse files

Gd advertiser and scanner shim

Bug: 143578947
Test: Devicepicker shows le devices
Change-Id: I5a59c791b2c37ada9d2dde0563dae69bb0039501
parent c6f881a6
Loading
Loading
Loading
Loading
+69 −5
Original line number Diff line number Diff line
@@ -30,18 +30,82 @@ namespace bluetooth {
namespace shim {

struct Advertising::impl {
  hci::LeAdvertisingManager* module_{nullptr};

  impl(hci::LeAdvertisingManager* module);
  impl(hci::LeAdvertisingManager* module, os::Handler* handler);
  ~impl();

  void StartAdvertising();
  void StopAdvertising();

  size_t GetNumberOfAdvertisingInstances() const;

 private:
  void OnScan(hci::Address address, hci::AddressType address_type);
  void OnTerminated(hci::ErrorCode code, uint8_t handle, uint8_t num_events);

  hci::AdvertiserId advertiser_id_{hci::LeAdvertisingManager::kInvalidId};

  hci::LeAdvertisingManager* advertising_manager_{nullptr};
  os::Handler* handler_;
};

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

Advertising::impl::impl(hci::LeAdvertisingManager* advertising_manager) : module_(advertising_manager) {}
Advertising::impl::impl(hci::LeAdvertisingManager* advertising_manager, os::Handler* handler)
    : advertising_manager_(advertising_manager), handler_(handler) {}

Advertising::impl::~impl() {}

void Advertising::impl::StartAdvertising() {
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s Already advertising; please stop prior to starting again", __func__);
    return;
  }

  hci::AdvertisingConfig config;
  advertiser_id_ =
      advertising_manager_->CreateAdvertiser(config, common::Bind(&impl::OnScan, common::Unretained(this)),
                                             common::Bind(&impl::OnTerminated, common::Unretained(this)), handler_);
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s Unable to start advertising", __func__);
    return;
  }
  LOG_DEBUG("%s Started advertising", __func__);
}

void Advertising::impl::StopAdvertising() {
  if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
    LOG_WARN("%s No active advertising", __func__);
    return;
  }
  advertising_manager_->RemoveAdvertiser(advertiser_id_);
  advertiser_id_ = hci::LeAdvertisingManager::kInvalidId;
  LOG_DEBUG("%s Stopped advertising", __func__);
}

void Advertising::impl::OnScan(hci::Address address, hci::AddressType address_type) {
  LOG_INFO("%s UNIMPLEMENTED Received le advert from:%s", __func__, address.ToString().c_str());
}

void Advertising::impl::OnTerminated(hci::ErrorCode code, uint8_t handle, uint8_t num_events) {
  LOG_INFO("%s UNIMPLEMENTED", __func__);
}

size_t Advertising::impl::GetNumberOfAdvertisingInstances() const {
  return advertising_manager_->GetNumberOfAdvertisingInstances();
}

size_t Advertising::GetNumberOfAdvertisingInstances() const {
  return pimpl_->GetNumberOfAdvertisingInstances();
}

void Advertising::StartAdvertising() {
  pimpl_->StartAdvertising();
}

void Advertising::StopAdvertising() {
  pimpl_->StopAdvertising();
}

/**
 * Module methods
 */
@@ -50,7 +114,7 @@ void Advertising::ListDependencies(ModuleList* list) {
}

void Advertising::Start() {
  pimpl_ = std::make_unique<impl>(GetDependency<hci::LeAdvertisingManager>());
  pimpl_ = std::make_unique<impl>(GetDependency<hci::LeAdvertisingManager>(), GetHandler());
}

void Advertising::Stop() {
+5 −0
Original line number Diff line number Diff line
@@ -29,6 +29,11 @@ class Advertising : public bluetooth::Module, public bluetooth::shim::IAdvertisi
  Advertising() = default;
  ~Advertising() = default;

  void StartAdvertising() override;
  void StopAdvertising() override;

  size_t GetNumberOfAdvertisingInstances() const override;

  static const ModuleFactory Factory;

 protected:
+7 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
#pragma once

#include <cstddef>

/**
 * The gd API exported to the legacy api
 */
@@ -22,6 +24,11 @@ namespace bluetooth {
namespace shim {

struct IAdvertising {
  virtual void StartAdvertising() = 0;
  virtual void StopAdvertising() = 0;

  virtual size_t GetNumberOfAdvertisingInstances() const = 0;

  virtual ~IAdvertising() {}
};

+32 −0
Original line number Diff line number Diff line
@@ -15,13 +15,45 @@
 */
#pragma once

#include <cstdint>
#include <functional>

/**
 * The gd API exported to the legacy api
 */
namespace bluetooth {
namespace shim {

struct AdvertisingReport {
  uint16_t extended_event_type;
  std::string string_address;
  uint8_t address_type;
  int8_t rssi;
  uint8_t* data;
  size_t len;
};

struct DirectedAdvertisingReport : public AdvertisingReport {
  DirectedAdvertisingReport(AdvertisingReport report) : AdvertisingReport(report) {}
  uint8_t directed_advertising_type;
};

struct ExtendedAdvertisingReport : public DirectedAdvertisingReport {
  ExtendedAdvertisingReport(AdvertisingReport report) : DirectedAdvertisingReport(report) {}
};

using AdvertisingReportCallback = std::function<void(AdvertisingReport report)>;
using DirectedAdvertisingReportCallback = std::function<void(DirectedAdvertisingReport report)>;
using ExtendedAdvertisingReportCallback = std::function<void(ExtendedAdvertisingReport report)>;
using ScanningTimeoutCallback = std::function<void()>;

struct IScanning {
  virtual void StartScanning(bool set_active, AdvertisingReportCallback advertising_callback,
                             DirectedAdvertisingReportCallback directed_advertising_callback,
                             ExtendedAdvertisingReportCallback extended_advertising_callback,
                             ScanningTimeoutCallback timeout_callback) = 0;
  virtual void StopScanning() = 0;

  virtual ~IScanning() {}
};

+183 −5
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@
#include <functional>
#include <memory>

#include "common/bind.h"
#include "hci/address.h"
#include "hci/hci_packets.h"
#include "hci/le_report.h"
#include "hci/le_scanning_manager.h"
#include "module.h"
#include "os/handler.h"
@@ -29,19 +31,195 @@
namespace bluetooth {
namespace shim {

struct Scanning::impl {
  hci::LeScanningManager* module_{nullptr};
constexpr size_t kAdvertisingReportBufferSize = 1024;

  impl(hci::LeScanningManager* module);
struct Scanning::impl : public hci::LeScanningManagerCallbacks {
  void StartScanning(bool set_active, AdvertisingReportCallback advertising_callback,
                     DirectedAdvertisingReportCallback directed_advertising_callback,
                     ExtendedAdvertisingReportCallback extended_advertising_callback,
                     ScanningTimeoutCallback timeout_callback);
  void StopScanning();

  void on_advertisements(std::vector<std::shared_ptr<hci::LeReport>>) override;
  void on_timeout() override;
  os::Handler* Handler() override;

  void OnStopped();

  impl(hci::LeScanningManager* scanning_manager, os::Handler* handler);
  ~impl();

 private:
  hci::LeScanningManager* scanning_manager_{nullptr};
  os::Handler* handler_;
  bool active_scanning_{true};

  AdvertisingReportCallback advertising_callback_;
  DirectedAdvertisingReportCallback directed_advertising_callback_;
  ExtendedAdvertisingReportCallback extended_advertising_callback_;
  ScanningTimeoutCallback timeout_callback_;
};

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

Scanning::impl::impl(hci::LeScanningManager* scanning_manager) : module_(scanning_manager) {}
Scanning::impl::impl(hci::LeScanningManager* scanning_manager, os::Handler* handler)
    : scanning_manager_(scanning_manager), handler_(handler) {}

Scanning::impl::~impl() {}

struct ExtendedEventTypeOptions {
  bool connectable{false};
  bool scannable{false};
  bool directed{false};
  bool scan_response{false};
  bool legacy{false};
  bool continuing{false};
  bool truncated{false};
};

constexpr uint16_t kBleEventConnectableBit = (0x0001 << 0);   // BLE_EVT_CONNECTABLE_BIT
constexpr uint16_t kBleEventScannableBit = (0x0001 << 1);     // BLE_EVT_SCANNABLE_BIT
constexpr uint16_t kBleEventDirectedBit = (0x0001 << 2);      // BLE_EVT_DIRECTED_BIT
constexpr uint16_t kBleEventScanResponseBit = (0x0001 << 3);  // BLE_EVT_SCAN_RESPONSE_BIT
constexpr uint16_t kBleEventLegacyBit = (0x0001 << 4);        // BLE_EVT_LEGACY_BIT
constexpr uint16_t kBleEventIncompleteContinuing = (0x0001 << 5);
constexpr uint16_t kBleEventIncompleteTruncated = (0x0001 << 6);

static void TransformToExtendedEventType(uint16_t* extended_event_type, ExtendedEventTypeOptions o) {
  ASSERT(extended_event_type != nullptr);
  *extended_event_type = (o.connectable ? kBleEventConnectableBit : 0) | (o.scannable ? kBleEventScannableBit : 0) |
                         (o.directed ? kBleEventDirectedBit : 0) | (o.scan_response ? kBleEventScanResponseBit : 0) |
                         (o.legacy ? kBleEventLegacyBit : 0) | (o.continuing ? kBleEventIncompleteContinuing : 0) |
                         (o.truncated ? kBleEventIncompleteTruncated : 0);
}

void Scanning::impl::on_advertisements(std::vector<std::shared_ptr<hci::LeReport>> reports) {
  for (auto le_report : reports) {
    AdvertisingReport report{
        .string_address = le_report->address_.ToString(),
        .address_type = static_cast<uint8_t>(le_report->address_type_),
        .rssi = le_report->rssi_,
        .extended_event_type = 0,
        .data = nullptr,
        .len = 0,
    };

    uint8_t advertising_data_buffer[kAdvertisingReportBufferSize];
    // Copy gap data, if any, into temporary buffer as payload for legacy stack.
    if (!le_report->gap_data_.empty()) {
      bzero(advertising_data_buffer, kAdvertisingReportBufferSize);
      uint8_t* p = advertising_data_buffer;
      for (auto gap_data : le_report->gap_data_) {
        *p++ = gap_data.size() + sizeof(gap_data.data_type_);
        *p++ = static_cast<uint8_t>(gap_data.data_type_);
        p = (uint8_t*)memcpy(p, &gap_data.data_[0], gap_data.data_.size()) + gap_data.data_.size();
      }
      report.data = advertising_data_buffer;
      report.len = p - report.data;
    }

    switch (le_report->GetReportType()) {
      case hci::LeReport::ReportType::ADVERTISING_EVENT:
        switch (le_report->advertising_event_type_) {
          case hci::AdvertisingEventType::ADV_IND:
            TransformToExtendedEventType(&report.extended_event_type,
                                         {.connectable = true, .scannable = true, .legacy = true});
            break;
          case hci::AdvertisingEventType::ADV_DIRECT_IND:
            TransformToExtendedEventType(&report.extended_event_type,
                                         {.connectable = true, .directed = true, .legacy = true});
            break;
          case hci::AdvertisingEventType::ADV_SCAN_IND:
            TransformToExtendedEventType(&report.extended_event_type, {.scannable = true, .legacy = true});
            break;
          case hci::AdvertisingEventType::ADV_NONCONN_IND:
            TransformToExtendedEventType(&report.extended_event_type, {.legacy = true});
            break;
          case hci::AdvertisingEventType::ADV_DIRECT_IND_LOW:  // SCAN_RESPONSE
            TransformToExtendedEventType(
                &report.extended_event_type,
                {.connectable = true, .scannable = true, .scan_response = true, .legacy = true});
            break;
          default:
            LOG_WARN("%s Unsupported event type:%s", __func__,
                     AdvertisingEventTypeText(le_report->advertising_event_type_).c_str());
            return;
        }
        advertising_callback_(report);
        break;

      case hci::LeReport::ReportType::DIRECTED_ADVERTISING_EVENT: {
        DirectedAdvertisingReport directed_report(report);
        std::shared_ptr<hci::DirectedLeReport> directed_le_report =
            std::static_pointer_cast<hci::DirectedLeReport>(le_report);
        directed_report.directed_advertising_type = static_cast<uint8_t>(directed_le_report->direct_address_type_);
        directed_advertising_callback_(directed_report);
      } break;

      case hci::LeReport::ReportType::EXTENDED_ADVERTISING_EVENT: {
        ExtendedAdvertisingReport extended_report(report);
        std::shared_ptr<hci::ExtendedLeReport> extended_le_report =
            std::static_pointer_cast<hci::ExtendedLeReport>(le_report);
        TransformToExtendedEventType(&report.extended_event_type, {.connectable = extended_le_report->connectable_,
                                                                   .scannable = extended_le_report->scannable_,
                                                                   .directed = extended_le_report->directed_,
                                                                   .scan_response = extended_le_report->scan_response_,
                                                                   .legacy = false,
                                                                   .continuing = !extended_le_report->complete_,
                                                                   .truncated = extended_le_report->truncated_});
        extended_advertising_callback_(extended_report);
      } break;
    }
  }
}

void Scanning::impl::on_timeout() {
  timeout_callback_();
}

os::Handler* Scanning::impl::Handler() {
  return handler_;
}

void Scanning::impl::StartScanning(bool set_active, AdvertisingReportCallback advertising_callback,
                                   DirectedAdvertisingReportCallback directed_advertising_callback,
                                   ExtendedAdvertisingReportCallback extended_advertising_callback,
                                   ScanningTimeoutCallback timeout_callback) {
  active_scanning_ = set_active;
  advertising_callback_ = advertising_callback;
  directed_advertising_callback_ = directed_advertising_callback;
  extended_advertising_callback_ = extended_advertising_callback;
  timeout_callback_ = timeout_callback;

  scanning_manager_->StartScan(this);
  LOG_DEBUG("%s Started le %s scanning", __func__, (active_scanning_) ? "active" : "passive");
}

void Scanning::impl::StopScanning() {
  LOG_DEBUG("%s Stopping le %s scanning", __func__, (active_scanning_) ? "active" : "passive");
  scanning_manager_->StopScan(common::Bind(&impl::OnStopped, common::Unretained(this)));
  advertising_callback_ = {};
  directed_advertising_callback_ = {};
  extended_advertising_callback_ = {};
  timeout_callback_ = {};
}

void Scanning::impl::OnStopped() {
  LOG_DEBUG("%s Stopped le %s scanning", __func__, (active_scanning_) ? "active" : "passive");
}

void Scanning::StartScanning(bool set_active, AdvertisingReportCallback advertising_callback,
                             DirectedAdvertisingReportCallback directed_advertising_callback,
                             ExtendedAdvertisingReportCallback extended_advertising_callback,
                             ScanningTimeoutCallback timeout_callback) {
  pimpl_->StartScanning(set_active, advertising_callback, directed_advertising_callback, extended_advertising_callback,
                        timeout_callback);
}

void Scanning::StopScanning() {
  pimpl_->StopScanning();
}

/**
 * Module methods
 */
@@ -50,7 +228,7 @@ void Scanning::ListDependencies(ModuleList* list) {
}

void Scanning::Start() {
  pimpl_ = std::make_unique<impl>(GetDependency<hci::LeScanningManager>());
  pimpl_ = std::make_unique<impl>(GetDependency<hci::LeScanningManager>(), GetHandler());
}

void Scanning::Stop() {
Loading