--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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