OSDN Git Service

stack: Periodic advertising scanner implementation
authorJakub Tyszkowski <jakub.tyszkowski@codecoup.pl>
Thu, 30 Apr 2020 10:42:01 +0000 (12:42 +0200)
committerJakub Pawlowski <jpawlowski@google.com>
Tue, 22 Sep 2020 12:08:58 +0000 (14:08 +0200)
This adds the ble_scanner_hci_interface for periodic advertising scan
and all the low level HCI commands and event handlers.

Bug: 150670922
Tag: #feature
Sponsor: jpawlowski@
Test: compilation
Change-Id: I20e7057a8806c5ca8ef9e7261e1c2b446135cbed

stack/Android.bp
stack/BUILD.gn
stack/btm/ble_scanner_hci_interface.cc [new file with mode: 0644]
stack/btm/ble_scanner_hci_interface.h [new file with mode: 0644]
stack/btm/btm_ble_int.h
stack/btu/btu_hcif.cc

index 78b4ff5..b6bf90c 100644 (file)
@@ -103,6 +103,7 @@ cc_library_static {
         "btm/ble_advertiser_hci_interface.cc",
         "acl/btm_acl.cc",
         "acl/ble_acl.cc",
+        "btm/ble_scanner_hci_interface.cc",
         "btm/btm_ble.cc",
         "btm/btm_ble_addr.cc",
         "btm/btm_ble_adv_filter.cc",
index ef837f1..8b9e74b 100644 (file)
@@ -77,6 +77,7 @@ static_library("stack") {
     "bnep/bnep_main.cc",
     "bnep/bnep_utils.cc",
     "btm/ble_advertiser_hci_interface.cc",
+    "btm/ble_scanner_hci_interface.cc",
     "btm/btm_acl.cc",
     "btm/btm_ble.cc",
     "btm/btm_ble_addr.cc",
diff --git a/stack/btm/ble_scanner_hci_interface.cc b/stack/btm/ble_scanner_hci_interface.cc
new file mode 100644 (file)
index 0000000..a6c281f
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2019 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * 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.
+ */
+
+#include "ble_scanner_hci_interface.h"
+
+#include <base/bind.h>
+
+#include "acl_api.h"
+#include "device/include/controller.h"
+#include "hcidefs.h"
+#include "hcimsgs.h"
+#include "log/log.h"
+
+namespace {
+BleScannerHciInterface* instance = nullptr;
+
+static void status_callback(base::Callback<void(uint8_t)> cb, uint8_t* data,
+                            uint16_t len) {
+  uint8_t status;
+
+  LOG_ASSERT(len == 1) << "Received bad response length: " << len;
+  STREAM_TO_UINT8(status, data);
+
+  DVLOG(1) << __func__ << " Received status_cb";
+  cb.Run(status);
+}
+
+static void status_handle_callback(base::Callback<void(uint8_t, uint16_t)> cb,
+                                   uint8_t* data, uint16_t len) {
+  uint8_t status;
+  uint16_t handle = HCI_INVALID_HANDLE;
+
+  LOG_ASSERT((len > 0) && (len < 4)) << "Received bad response length: " << len;
+  uint8_t* pp = data;
+  STREAM_TO_UINT8(status, pp);
+
+  if (status == HCI_SUCCESS) {
+    LOG_ASSERT(len == 3) << "Received bad response length: " << len;
+
+    STREAM_TO_UINT16(handle, pp);
+    handle = handle & 0x0EFF;
+
+    DVLOG(1) << __func__ << " Received status_handle_callback";
+  } else {
+    DVLOG(1) << __func__ << " hci response error code: " << int{status};
+  }
+  cb.Run(status, handle);
+}
+
+/**
+ * BleScannerHciInterface allows the caller to sync to a periodic advertising
+ * train and receive periodic advertising data events through a registered
+ * observer's callbacks. It also provides a synchronisation transfer API,
+ * including in-controller allow list support. The right feature-complete
+ * interface implementation is chosen during the init phase based on the
+ * controller's list of supported features.
+ */
+class BleScannerImplBase : public BleScannerHciInterface {
+ public:
+  void SetScanEventObserver(ScanEventObserver* observer) override {
+    VLOG(1) << __func__;
+    // TODO: Support multiple observers if ever needed.
+    scan_event_observer = observer;
+  }
+
+  void PeriodicScanStart(uint8_t options, uint8_t set_id, uint8_t adv_addr_type,
+                         const RawAddress& adv_addr, uint16_t skip_num,
+                         uint16_t sync_timeout,
+                         uint8_t sync_cte_type) override {
+    VLOG(1) << __func__;
+    btsnd_hcic_ble_periodic_advertising_create_sync(
+        options, set_id, adv_addr_type, adv_addr, skip_num, sync_timeout,
+        sync_cte_type);
+  }
+
+  void PeriodicScanCancelStart(status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hcic_ble_periodic_advertising_create_sync_cancel(
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicScanTerminate(uint16_t sync_handle,
+                             status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hcic_ble_periodic_advertising_terminate_sync(
+        sync_handle, base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicScanResultEvtEnable(uint16_t sync_handle, bool enable,
+                                   status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hcic_ble_set_periodic_advertising_receive_enable(
+        sync_handle, enable,
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvertiserListGetSize(
+      BleScannerHciInterface::list_size_cb command_complete) override {
+    VLOG(1) << __func__;
+    command_complete.Run(
+        controller_get_interface()->get_ble_periodic_advertiser_list_size());
+  }
+
+  void PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,
+                                       RawAddress& adv_addr, uint8_t set_id,
+                                       status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_add_device_to_periodic_advertiser_list(
+        adv_addr_type, adv_addr, set_id,
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,
+                                          RawAddress& adv_addr, uint8_t set_id,
+                                          status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_remove_device_from_periodic_advertiser_list(
+        adv_addr_type, adv_addr, set_id,
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvertiserListClear(status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_clear_periodic_advertiser_list(
+        base::Bind(&status_callback, std::move(command_complete)));
+  };
+
+  void PeriodicAdvSyncTransfer(
+      const RawAddress& bd_addr, uint16_t service_data, uint16_t sync_handle,
+      BleScannerHciInterface::handle_cb command_complete) override {
+    VLOG(1) << __func__;
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    btsnd_hcic_ble_periodic_advertising_sync_transfer(
+        acl_handle, service_data, sync_handle,
+        base::Bind(&status_handle_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvSetInfoTransfer(const RawAddress& bd_addr,
+                                  uint16_t service_data, uint8_t adv_handle,
+                                  handle_cb command_complete) override {
+    VLOG(1) << __func__;
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    btsnd_hcic_ble_periodic_advertising_set_info_transfer(
+        acl_handle, service_data, adv_handle,
+        base::Bind(&status_handle_callback, std::move(command_complete)));
+  }
+
+  void SetPeriodicAdvSyncTransferParams(const RawAddress& bd_addr, uint8_t mode,
+                                        uint16_t skip, uint16_t sync_timeout,
+                                        uint8_t cte_type, bool set_defaults,
+                                        status_cb command_complete) override {
+    VLOG(1) << __func__;
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    if (set_defaults)
+      btsnd_hcic_ble_set_default_periodic_advertising_sync_transfer_params(
+          acl_handle, mode, skip, sync_timeout, cte_type,
+          base::Bind(&status_callback, std::move(command_complete)));
+    else
+      btsnd_hcic_ble_set_periodic_advertising_sync_transfer_params(
+          acl_handle, mode, skip, sync_timeout, cte_type,
+          base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void OnPeriodicAdvSyncEstablished(uint8_t status, uint16_t sync_handle,
+                                    uint8_t adv_sid, uint8_t adv_addr_type,
+                                    RawAddress adv_addr, uint8_t adv_phy,
+                                    uint16_t adv_interval,
+                                    uint8_t adv_clock_accuracy) {
+    if (scan_event_observer) {
+      scan_event_observer->OnPeriodicScanEstablished(
+          status, sync_handle, adv_sid, adv_addr_type, adv_addr, adv_phy,
+          adv_interval, adv_clock_accuracy);
+    }
+  }
+
+  void OnPeriodicScanResult(uint16_t sync_handle, uint8_t tx_power, int8_t rssi,
+                            uint8_t cte_type, uint8_t pkt_data_status,
+                            uint8_t pkt_data_len, uint8_t* p_pkt_data) {
+    // The observer should handle the caching and reassembly of the fragmented
+    // packet.
+    if (scan_event_observer) {
+      scan_event_observer->OnPeriodicScanResult(sync_handle, tx_power, rssi,
+                                                cte_type, pkt_data_status,
+                                                pkt_data_len, p_pkt_data);
+    }
+  }
+
+  void OnPeriodicSyncLost(uint16_t sync_handle) {
+    if (scan_event_observer)
+      scan_event_observer->OnPeriodicScanLost(sync_handle);
+  }
+
+ private:
+  ScanEventObserver* scan_event_observer = nullptr;
+};
+
+class BleScannerListImpl : public virtual BleScannerImplBase {
+  void PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,
+                                       RawAddress& adv_addr, uint8_t set_id,
+                                       status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_add_device_to_periodic_advertiser_list(
+        adv_addr_type, adv_addr, set_id,
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,
+                                          RawAddress& adv_addr, uint8_t set_id,
+                                          status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_remove_device_from_periodic_advertiser_list(
+        adv_addr_type, adv_addr, set_id,
+        base::Bind(&status_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvertiserListClear(status_cb command_complete) override {
+    VLOG(1) << __func__;
+    btsnd_hci_ble_clear_periodic_advertiser_list(
+        base::Bind(&status_callback, std::move(command_complete)));
+  };
+};
+
+class BleScannerSyncTransferImpl : public virtual BleScannerImplBase {
+  void PeriodicAdvSyncTransfer(
+      const RawAddress& bd_addr, uint16_t service_data, uint16_t sync_handle,
+      BleScannerHciInterface::handle_cb command_complete) override {
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    btsnd_hcic_ble_periodic_advertising_sync_transfer(
+        acl_handle, service_data, sync_handle,
+        base::Bind(&status_handle_callback, std::move(command_complete)));
+  }
+
+  void PeriodicAdvSetInfoTransfer(const RawAddress& bd_addr,
+                                  uint16_t service_data, uint8_t adv_handle,
+                                  handle_cb command_complete) override {
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    btsnd_hcic_ble_periodic_advertising_set_info_transfer(
+        acl_handle, service_data, adv_handle,
+        base::Bind(&status_handle_callback, std::move(command_complete)));
+  }
+
+  void SetPeriodicAdvSyncTransferParams(const RawAddress& bd_addr, uint8_t mode,
+                                        uint16_t skip, uint16_t sync_timeout,
+                                        uint8_t cte_type, bool set_defaults,
+                                        status_cb command_complete) override {
+    uint16_t acl_handle = acl_get_hci_handle_for_hcif(bd_addr, BT_TRANSPORT_LE);
+
+    if (acl_handle == HCI_INVALID_HANDLE) {
+      LOG(ERROR) << __func__
+                 << ": Wrong mode: no LE link exist or LE not supported";
+      return;
+    }
+
+    if (set_defaults)
+      btsnd_hcic_ble_set_default_periodic_advertising_sync_transfer_params(
+          acl_handle, mode, skip, sync_timeout, cte_type,
+          base::Bind(&status_callback, std::move(command_complete)));
+    else
+      btsnd_hcic_ble_set_periodic_advertising_sync_transfer_params(
+          acl_handle, mode, skip, sync_timeout, cte_type,
+          base::Bind(&status_callback, std::move(command_complete)));
+  }
+};
+
+class BleScannerCompleteImpl : public BleScannerListImpl,
+                               public BleScannerSyncTransferImpl {
+  // Not much to do here :)
+};
+
+}  // namespace
+
+void BleScannerHciInterface::Initialize() {
+  VLOG(1) << __func__;
+  LOG_ASSERT(instance == nullptr) << "Was already initialized.";
+
+  if ((controller_get_interface()->get_ble_periodic_advertiser_list_size()) &&
+      (controller_get_interface()
+           ->supports_ble_periodic_advertising_sync_transfer_sender())) {
+    LOG(INFO) << "Advertiser list in controller can be used";
+    LOG(INFO) << "Periodic Adv Sync Transfer Sender role is supported";
+    instance = new BleScannerCompleteImpl();
+  } else if (controller_get_interface()
+                 ->supports_ble_periodic_advertising_sync_transfer_sender()) {
+    LOG(INFO) << "Periodic Adv Sync Transfer Sender role is supported";
+    instance = new BleScannerSyncTransferImpl();
+  } else if (controller_get_interface()
+                 ->get_ble_periodic_advertiser_list_size()) {
+    LOG(INFO) << "Periodic Adv Sync Transfer Recipient role is supported";
+    instance = new BleScannerListImpl();
+  }
+  // TODO: Implement periodic adv. sync. recipient role if ever needed.
+}
+
+BleScannerHciInterface* BleScannerHciInterface::Get() { return instance; }
+
+void BleScannerHciInterface::CleanUp() {
+  VLOG(1) << __func__;
+
+  delete instance;
+  instance = nullptr;
+}
+
+void btm_ble_process_periodic_adv_sync_est_evt(uint8_t data_len,
+                                               uint8_t* data) {
+  uint16_t sync_handle, adv_interval;
+  uint8_t status, adv_sid, adv_addr_type, adv_phy, adv_clock_accuracy;
+  RawAddress adv_addr;
+
+  VLOG(1) << __func__;
+
+  LOG_ASSERT(data_len == 15)
+      << "Malformed LE Periodic Advertising Sync Est. Event from controller";
+
+  STREAM_TO_UINT8(status, data);
+  STREAM_TO_UINT16(sync_handle, data);
+  STREAM_TO_UINT8(adv_sid, data);
+  STREAM_TO_UINT8(adv_addr_type, data);
+  STREAM_TO_BDADDR(adv_addr, data);
+  STREAM_TO_UINT8(adv_phy, data);
+  STREAM_TO_UINT16(adv_interval, data);
+  STREAM_TO_UINT8(adv_clock_accuracy, data);
+
+  if (BleScannerHciInterface::Get()) {
+    static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
+        ->OnPeriodicAdvSyncEstablished(status, sync_handle, adv_sid,
+                                       adv_addr_type, adv_addr, adv_phy,
+                                       adv_interval, adv_clock_accuracy);
+  }
+}
+
+void btm_ble_process_periodic_adv_pkt(uint8_t data_len, uint8_t* data) {
+  uint8_t* p = data;
+  uint16_t sync_handle;
+  uint8_t tx_power, cte_type, pkt_data_status, pkt_data_len;
+  int8_t rssi;
+
+  LOG_ASSERT(data_len >= 7)
+      << "Malformed LE Periodic Advertising Report Event from controller";
+
+  STREAM_TO_UINT16(sync_handle, p);
+  STREAM_TO_UINT8(tx_power, p);
+  STREAM_TO_INT8(rssi, p);
+  STREAM_TO_UINT8(cte_type, p);
+  STREAM_TO_UINT8(pkt_data_status, p);
+  STREAM_TO_UINT8(pkt_data_len, p);
+
+  uint8_t* pkt_data = p;
+  p += pkt_data_len;
+
+  if (p > data + data_len) {
+    LOG(ERROR) << __func__ << " Invalid pkt_data_len: " << int{pkt_data_len};
+    return;
+  }
+
+  if (rssi >= 21 && rssi <= 126) {
+    LOG(ERROR) << __func__
+               << " bad rssi value in advertising report: " << int{rssi};
+  }
+
+  if (BleScannerHciInterface::Get()) {
+    static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
+        ->OnPeriodicScanResult(sync_handle, tx_power, rssi, cte_type,
+                               pkt_data_status, pkt_data_len, pkt_data);
+  }
+}
+
+void btm_ble_process_periodic_adv_sync_lost_evt(uint8_t data_len,
+                                                uint8_t* data) {
+  uint16_t sync_handle;
+
+  STREAM_TO_UINT16(sync_handle, data);
+
+  if (BleScannerHciInterface::Get()) {
+    static_cast<BleScannerImplBase*>(BleScannerHciInterface::Get())
+        ->OnPeriodicSyncLost(sync_handle);
+  }
+}
diff --git a/stack/btm/ble_scanner_hci_interface.h b/stack/btm/ble_scanner_hci_interface.h
new file mode 100644 (file)
index 0000000..f7b233c
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2019 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * 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.
+ */
+
+#ifndef BLE_SCANNER_HCI_INTERFACE_H
+#define BLE_SCANNER_HCI_INTERFACE_H
+
+#include <base/callback.h>
+
+#include <vector>
+
+#include "stack/include/bt_types.h"
+
+class BleScannerHciInterface {
+ public:
+  using status_cb = base::Callback<void(uint8_t /* status */)>;
+  using list_size_cb = base::Callback<void(int8_t /* list_size */)>;
+  using handle_cb =
+      base::Callback<void(uint8_t /* status */, uint16_t /* adv_handle */)>;
+
+  static void Initialize();
+  static BleScannerHciInterface* Get();
+  static void CleanUp();
+
+  virtual ~BleScannerHciInterface() = default;
+
+  class ScanEventObserver {
+   public:
+    virtual ~ScanEventObserver() = default;
+    virtual void OnPeriodicScanResult(uint16_t sync_handle, uint8_t tx_power,
+                                      int8_t rssi, uint8_t cte_type,
+                                      uint8_t pkt_data_status,
+                                      uint8_t pkt_data_len,
+                                      const uint8_t* pkt_data) = 0;
+    virtual void OnPeriodicScanEstablished(
+        uint8_t status, uint16_t sync_handle, uint8_t set_id,
+        uint8_t adv_addr_type, const RawAddress& adv_addr, uint8_t adv_phy,
+        uint16_t adv_interval, uint8_t adv_clock_accuracy) = 0;
+    virtual void OnPeriodicScanLost(uint16_t sync_handle) = 0;
+  };
+
+  virtual void SetScanEventObserver(ScanEventObserver* observer) = 0;
+
+  /**
+   * Used to synchronize with a periodic advertising train from an advertiser
+   * and begin receiving periodic advertising packets.
+   *
+   * @param options bit 0: whether to use advertiser list, adv_sid,
+   * adv_addr_type and adv_addr parameters are being used otherwise, bit 1:
+   * whether reporting is initially disabled, all other bits: Reserved for
+   * future use
+   * @param adv_sid advertising set ID
+   * @param adv_addr_type advertiser device address type
+   * @param adv_addr advertiser device address
+   * @param skip_num the maximum number of periodic advertising events that can
+   * be skipped after a successful receive. Range: 0x0000 to 0x01F3.
+   * @param sync_timeout synchronization timeout for the periodic advertising
+   * train, Range: 0x000A to 0x4000, Time = N*10 ms, Range: 100 ms to 163.84s
+   * @param sync_cte_type bit 0: do not sync to packets with an AoA Constant
+   * Tone Extension, bit 1: do not sync to packets with an AoD Constant Tone
+   * Extension with 1 μs slots, bit 2: do not sync to packets with an AoD
+   * Constant Tone Extension with 2 μs slots, bit 3: do not sync to packets with
+   * a type 3 Constant Tone Extension (currently reserved for future use),
+   * bit 4: do not sync to packets without a Constant Tone Extension, all other
+   * bits: reserved for future use.
+   */
+  virtual void PeriodicScanStart(uint8_t options, uint8_t set_id,
+                                 uint8_t adv_addr_type,
+                                 const RawAddress& adv_addr, uint16_t skip_num,
+                                 uint16_t sync_timeout,
+                                 uint8_t sync_cte_type) = 0;
+
+  /**
+   * Used to cancel the HCI_LE_Periodic_Advertising_Create_Sync command while it
+   * is pending.
+   *
+   * @param cb status callback
+   */
+  virtual void PeriodicScanCancelStart(status_cb cb) = 0;
+
+  /**
+   * Used to stop reception of the periodic advertising train identified by the
+   * Sync_Handle parameter.
+   *
+   * @param sync_handle synced advertising handle
+   * @param cb status callback
+   */
+  virtual void PeriodicScanTerminate(uint16_t sync_handle, status_cb cb) = 0;
+
+  /**
+   * Enable or disable reports for the periodic advertising train defined by the
+   * sync_handle.
+   *
+   * @param sync_handle synced advewrtising handle
+   * @param enable whether enable or disable the advertising reports
+   * @param cb  status callback
+   */
+  virtual void PeriodicScanResultEvtEnable(uint16_t sync_handle, bool enable,
+                                           status_cb cb) = 0;
+
+  /**
+   * Used to add an entry, consisting of a single device address and SID, to the
+   * Periodic Advertiser list stored in the Controller. Any additions to the
+   * Periodic Advertiser list take effect immediately. If the entry is already
+   * on the list, the Controller shall return the error code Invalid HCI Command
+   * Parameters (0x12).
+   *
+   * @param adv_addr_type advertiser device address type
+   * @param adv_addr advertiser device address
+   * @param adv_sid advertising set ID
+   * @param cb status callback
+   */
+  virtual void PeriodicAdvertiserListAddDevice(uint8_t adv_addr_type,
+                                               RawAddress& adv_addr,
+                                               uint8_t adv_sid,
+                                               status_cb cb) = 0;
+  /**
+   * Remove one entry from the list of Periodic Advertisers stored in the
+   * Controller. Removals from the Periodic Advertisers List take effect
+   * immediately.
+   *
+   * @param adv_addr_type advertiser device address type
+   * @param adv_addr advertiser device address
+   * @param adv_sid advertising set ID
+   * @param cb status callback
+   */
+  virtual void PeriodicAdvertiserListRemoveDevice(uint8_t adv_addr_type,
+                                                  RawAddress& adv_addr,
+                                                  uint8_t adv_sid,
+                                                  status_cb cb) = 0;
+
+  /**
+   * Remove all entries from the list of Periodic Advertisers in the Controller.
+   *
+   * @param cb status callback
+   */
+  virtual void PeriodicAdvertiserListClear(status_cb cb) = 0;
+
+  /**
+   * Read the total number of Periodic Advertiser list entries that can be
+   * stored in the Controller.
+   *
+   * @param cb status and advertiser list size callback
+   */
+  virtual void PeriodicAdvertiserListGetSize(list_size_cb cb) = 0;
+
+  /**
+   * Send synchronization information about the periodic advertising train
+   * identified by the sync_handle parameter to a connected device.
+   *
+   * @param bd_addr connected peer device address to whom sync data is
+   * transferred
+   * @param service_data a value provided by the Host
+   * @param sync_handle synced advewrtising handle
+   * @param cb status and connection handle callback
+   */
+  virtual void PeriodicAdvSyncTransfer(const RawAddress& bd_addr,
+                                       uint16_t service_data,
+                                       uint16_t sync_handle, handle_cb cb) = 0;
+
+  /**
+   * Send synchronization information about the periodic advertising in an
+   * advertising set to a connected device.
+   *
+   * @param bd_addr connected peer device address to whom set info is
+   * transferred
+   * @param service_data a value provided by the Host
+   * @param sync_handle synced advertising handle
+   * @param cb status and connection handle callback
+   */
+  virtual void PeriodicAdvSetInfoTransfer(const RawAddress& bd_addr,
+                                          uint16_t service_data,
+                                          uint8_t sync_handle,
+                                          handle_cb cb) = 0;
+
+  /**
+   * Specify how the Controller will process periodic advertising
+   * synchronization information received from the device identified by the
+   * bd_addr
+   *
+   * @param bd_addr connected peer device address who transfers the sync data
+   * @param mode 0x00: No attempt is made to synchronize to the periodic
+   * advertising and no HCI_LE_Periodic_Advertising_Sync_Transfer_Received event
+   * is sent to the Host. 0x01: An
+   * HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent to the
+   * Host. HCI_LE_Periodic_Advertising_Report events will be disabled. 0x02: An
+   * HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent to the
+   * Host. HCI_LE_Periodic_Advertising_Report events will be enabled. All other
+   * values: Reserved for future use.
+   * @param skip The number of periodic advertising packets that can be skipped
+   * after a successful receive, Range: 0x0000 to 0x01F3
+   * @param sync_timeout Synchronization timeout for the periodic advertising
+   * train. Range: 0x000A to 0x4000. Time = N*10 ms. Time Range: 100 ms to
+   * 163.84 s
+   * @param cte_type bit 0: do not sync to packets with an AoA Constant Tone
+   * Extension, bit 1: do not sync to packets with an AoD Constant Tone
+   * Extension with 1 μs slots, bit 2: do not sync to packets with an AoD
+   * Constant Tone Extension with 2 μs slots, bit 4: do not sync to packets
+   * without a Constant Tone Extension, all other values: reserved for future
+   * use.
+   * @param set_defaults whether to send
+   * HCI_LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAM or
+   * HCI_LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAM.
+   * @param cb status callback
+   */
+  virtual void SetPeriodicAdvSyncTransferParams(const RawAddress& bd_addr,
+                                                uint8_t mode, uint16_t skip,
+                                                uint16_t sync_timeout,
+                                                uint8_t cte_type,
+                                                bool set_defaults,
+                                                status_cb cb) = 0;
+
+  static constexpr uint8_t kOptUseAdvertiserList = 0x01;
+  static constexpr uint8_t kOptReportsInitiallyEnabled = 0x02;
+};
+
+#endif  // BLE_SCANNER_HCI_INTERFACE_H
index 0f33d04..b0abcce 100644 (file)
@@ -36,6 +36,9 @@
 #include "smp_api.h"
 
 extern void btm_ble_refresh_raddr_timer_timeout(void* data);
+extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len, uint8_t* p);
+extern void btm_ble_process_periodic_adv_pkt(uint8_t len, uint8_t* p);
+extern void btm_ble_process_periodic_adv_sync_lost_evt(uint8_t len, uint8_t* p);
 extern tBTM_STATUS btm_ble_read_remote_name(const RawAddress& remote_bda,
                                             tBTM_CMPL_CB* p_cb);
 extern bool btm_ble_cancel_remote_name(const RawAddress& remote_bda);
index e3260e6..fc65144 100644 (file)
@@ -425,6 +425,18 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) {
           btm_acl_process_sca_cmpl_pkt(ble_evt_len, p);
           break;
 
+        case HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT:
+          btm_ble_process_periodic_adv_sync_est_evt(ble_evt_len, p);
+          break;
+
+        case HCI_BLE_PERIODIC_ADV_REPORT_EVT:
+          btm_ble_process_periodic_adv_pkt(ble_evt_len, p);
+          break;
+
+        case HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT:
+          btm_ble_process_periodic_adv_sync_lost_evt(ble_evt_len, p);
+          break;
+
         case HCI_BLE_CIS_EST_EVT:
         case HCI_BLE_CREATE_BIG_CPL_EVT:
         case HCI_BLE_TERM_BIG_CPL_EVT: