You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
730 lines
26 KiB
730 lines
26 KiB
/****************************************************************************** |
|
* |
|
* Copyright (C) 2016 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. |
|
* |
|
******************************************************************************/ |
|
|
|
#include "ble_advertiser_hci_interface.h" |
|
#include <base/callback.h> |
|
#include <base/location.h> |
|
#include <base/logging.h> |
|
#include <queue> |
|
#include <utility> |
|
#include "btm_api.h" |
|
#include "btm_ble_api.h" |
|
#include "btm_int_types.h" |
|
#include "device/include/controller.h" |
|
#include "hcidefs.h" |
|
|
|
#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8 |
|
#define BTM_BLE_MULTI_ADV_ENB_LEN 3 |
|
#define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24 |
|
#define BTM_BLE_AD_DATA_LEN 31 |
|
#define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN (BTM_BLE_AD_DATA_LEN + 3) |
|
|
|
#define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 |
|
#define HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD 6 |
|
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 |
|
#define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_RSP 31 |
|
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31 |
|
|
|
using status_cb = BleAdvertiserHciInterface::status_cb; |
|
|
|
using hci_cmd_cb = base::Callback<void(uint8_t* /* return_parameters */, |
|
uint16_t /* return_parameters_length*/)>; |
|
extern void btu_hcif_send_cmd_with_cb( |
|
const tracked_objects::Location& posted_from, uint16_t opcode, |
|
uint8_t* params, uint8_t params_len, hci_cmd_cb cb); |
|
|
|
namespace { |
|
BleAdvertiserHciInterface* instance = nullptr; |
|
|
|
void btm_ble_multi_adv_vsc_cmpl_cback(uint8_t expected_opcode, |
|
status_cb command_complete, |
|
uint8_t* param, uint16_t param_len) { |
|
uint8_t status, subcode; |
|
|
|
// All multi-adv commands respond with status and inst_id. |
|
LOG_ASSERT(param_len == 2) << "Received bad response length to multi-adv VSC"; |
|
|
|
STREAM_TO_UINT8(status, param); |
|
STREAM_TO_UINT8(subcode, param); |
|
|
|
VLOG(1) << "subcode = " << +subcode << ", status: " << +status; |
|
|
|
if (expected_opcode != subcode) { |
|
LOG(ERROR) << "unexpected VSC cmpl, expect: " << +subcode |
|
<< " get: " << +expected_opcode; |
|
return; |
|
} |
|
|
|
command_complete.Run(status); |
|
} |
|
|
|
void parameters_response_parser(BleAdvertiserHciInterface::parameters_cb cb, |
|
uint8_t* ret_params, uint16_t ret_params_len) { |
|
uint8_t status; |
|
int8_t tx_power; |
|
|
|
uint8_t* pp = ret_params; |
|
STREAM_TO_UINT8(status, pp); |
|
STREAM_TO_INT8(tx_power, pp); |
|
|
|
cb.Run(status, tx_power); |
|
} |
|
|
|
void known_tx_pwr(BleAdvertiserHciInterface::parameters_cb cb, int8_t tx_power, |
|
uint8_t status) { |
|
cb.Run(status, tx_power); |
|
} |
|
|
|
class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface { |
|
void SendAdvCmd(const tracked_objects::Location& posted_from, |
|
uint8_t param_len, uint8_t* param_buf, |
|
status_cb command_complete) { |
|
btu_hcif_send_cmd_with_cb(posted_from, HCI_BLE_MULTI_ADV_OCF, param_buf, |
|
param_len, |
|
base::Bind(&btm_ble_multi_adv_vsc_cmpl_cback, |
|
param_buf[0], command_complete)); |
|
} |
|
|
|
void ReadInstanceCount( |
|
base::Callback<void(uint8_t /* inst_cnt*/)> cb) override { |
|
cb.Run(BTM_BleMaxMultiAdvInstanceCount()); |
|
} |
|
|
|
void SetAdvertisingEventObserver( |
|
AdvertisingEventObserver* observer) override { |
|
this->advertising_event_observer = observer; |
|
} |
|
|
|
void SetParameters(uint8_t handle, uint16_t properties, uint32_t adv_int_min, |
|
uint32_t adv_int_max, uint8_t channel_map, |
|
uint8_t own_address_type, const RawAddress& own_address, |
|
uint8_t peer_address_type, const RawAddress& peer_address, |
|
uint8_t filter_policy, int8_t tx_power, |
|
uint8_t primary_phy, uint8_t secondary_max_skip, |
|
uint8_t secondary_phy, uint8_t advertising_sid, |
|
uint8_t scan_request_notify_enable, |
|
parameters_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
uint8_t param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN]; |
|
memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM); |
|
UINT16_TO_STREAM(pp, adv_int_min); |
|
UINT16_TO_STREAM(pp, adv_int_max); |
|
|
|
if (properties == 0x0013) { |
|
UINT8_TO_STREAM(pp, 0x00); // ADV_IND |
|
} else if (properties == 0x0012) { |
|
UINT8_TO_STREAM(pp, 0x02); // ADV_SCAN_IND |
|
} else if (properties == 0x0010) { |
|
UINT8_TO_STREAM(pp, 0x03); // ADV_NONCONN_IND |
|
} else { |
|
LOG(ERROR) << "Unsupported advertisement type selected:" << std::hex |
|
<< properties; |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT, 0); |
|
return; |
|
} |
|
|
|
UINT8_TO_STREAM(pp, own_address_type); |
|
BDADDR_TO_STREAM(pp, own_address); |
|
UINT8_TO_STREAM(pp, peer_address_type); |
|
BDADDR_TO_STREAM(pp, peer_address); |
|
UINT8_TO_STREAM(pp, channel_map); |
|
UINT8_TO_STREAM(pp, filter_policy); |
|
UINT8_TO_STREAM(pp, handle); |
|
INT8_TO_STREAM(pp, tx_power); |
|
|
|
SendAdvCmd( |
|
FROM_HERE, BTM_BLE_MULTI_ADV_SET_PARAM_LEN, param, |
|
base::Bind(&known_tx_pwr, std::move(command_complete), tx_power)); |
|
} |
|
|
|
void SetAdvertisingData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, uint8_t data_length, |
|
uint8_t* data, status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
uint8_t param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN]; |
|
memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_WRITE_ADV_DATA); |
|
UINT8_TO_STREAM(pp, data_length); |
|
ARRAY_TO_STREAM(pp, data, data_length); |
|
param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1] = handle; |
|
|
|
SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param, |
|
command_complete); |
|
} |
|
|
|
void SetScanResponseData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, |
|
uint8_t scan_response_data_length, |
|
uint8_t* scan_response_data, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
uint8_t param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN]; |
|
memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA); |
|
UINT8_TO_STREAM(pp, scan_response_data_length); |
|
ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length); |
|
param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1] = handle; |
|
|
|
SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param, |
|
command_complete); |
|
} |
|
|
|
void SetRandomAddress(uint8_t handle, const RawAddress& random_address, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
uint8_t param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN]; |
|
memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR); |
|
BDADDR_TO_STREAM(pp, random_address); |
|
UINT8_TO_STREAM(pp, handle); |
|
|
|
SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN, param, |
|
command_complete); |
|
} |
|
|
|
void Enable(uint8_t enable, std::vector<SetEnableData> sets, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
if (sets.size() != 1) { |
|
LOG(ERROR) << "Trying to enable multiple sets in VSC implemenetation!"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); |
|
return; |
|
} |
|
SetEnableData& set = sets[0]; |
|
|
|
if (set.max_extended_advertising_events) { |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); |
|
return; |
|
} |
|
|
|
uint8_t param[BTM_BLE_MULTI_ADV_ENB_LEN]; |
|
memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_ENB); |
|
UINT8_TO_STREAM(pp, enable); |
|
UINT8_TO_STREAM(pp, set.handle); |
|
|
|
SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_ENB_LEN, param, |
|
command_complete); |
|
} |
|
|
|
void SetPeriodicAdvertisingParameters(uint8_t, uint16_t, uint16_t, uint16_t, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << " VSC can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
void SetPeriodicAdvertisingData(uint8_t, uint8_t, uint8_t, uint8_t*, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << " VSC can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
void SetPeriodicAdvertisingEnable(uint8_t, uint8_t, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << " VSC can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
bool QuirkAdvertiserZeroHandle() override { |
|
// Android BT HCI Requirements version 0.96 and below specify that handle 0 |
|
// is equal to standard HCI interface, and should be accessed using non-VSC |
|
// commands. |
|
LOG(INFO) << "QuirkAdvertiserZeroHandle in use"; |
|
return true; |
|
} |
|
|
|
void RemoveAdvertisingSet(uint8_t handle, |
|
status_cb command_complete) override { |
|
// VSC Advertising don't have remove method. |
|
command_complete.Run(0); |
|
} |
|
|
|
public: |
|
static void VendorSpecificEventCback(uint8_t length, uint8_t* p) { |
|
VLOG(1) << __func__; |
|
|
|
LOG_ASSERT(p); |
|
uint8_t sub_event, adv_inst, change_reason; |
|
uint16_t conn_handle; |
|
|
|
STREAM_TO_UINT8(sub_event, p); |
|
length--; |
|
|
|
if (sub_event != HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG || length != 4) { |
|
return; |
|
} |
|
|
|
STREAM_TO_UINT8(adv_inst, p); |
|
STREAM_TO_UINT8(change_reason, p); |
|
STREAM_TO_UINT16(conn_handle, p); |
|
|
|
AdvertisingEventObserver* observer = |
|
((BleAdvertiserVscHciInterfaceImpl*)BleAdvertiserHciInterface::Get()) |
|
->advertising_event_observer; |
|
if (observer) |
|
observer->OnAdvertisingSetTerminated(change_reason, adv_inst, conn_handle, |
|
0x00); |
|
} |
|
|
|
private: |
|
AdvertisingEventObserver* advertising_event_observer = nullptr; |
|
}; |
|
|
|
void adv_cmd_cmpl_cback(status_cb cb, uint8_t* return_parameters, |
|
uint16_t return_parameters_length) { |
|
uint8_t status = *return_parameters; |
|
cb.Run(status); |
|
} |
|
|
|
class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface { |
|
void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode, |
|
uint8_t* param_buf, uint8_t param_buf_len, |
|
status_cb command_complete) { |
|
btu_hcif_send_cmd_with_cb( |
|
posted_from, opcode, param_buf, param_buf_len, |
|
base::Bind(&adv_cmd_cmpl_cback, command_complete)); |
|
} |
|
|
|
void ReadInstanceCount( |
|
base::Callback<void(uint8_t /* inst_cnt*/)> cb) override { |
|
cb.Run(1); |
|
} |
|
|
|
void SetAdvertisingEventObserver( |
|
AdvertisingEventObserver* observer) override {} |
|
|
|
void SetParameters(uint8_t handle, uint16_t properties, uint32_t adv_int_min, |
|
uint32_t adv_int_max, uint8_t channel_map, |
|
uint8_t own_address_type, |
|
const RawAddress& /* own_address */, |
|
uint8_t peer_address_type, const RawAddress& peer_address, |
|
uint8_t filter_policy, int8_t tx_power, |
|
uint8_t primary_phy, uint8_t secondary_max_skip, |
|
uint8_t secondary_phy, uint8_t advertising_sid, |
|
uint8_t scan_request_notify_enable, |
|
parameters_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
uint8_t param[HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS]; |
|
|
|
uint8_t* pp = param; |
|
UINT16_TO_STREAM(pp, adv_int_min); |
|
UINT16_TO_STREAM(pp, adv_int_max); |
|
|
|
if (properties == 0x0013) { |
|
UINT8_TO_STREAM(pp, 0x00); // ADV_IND |
|
} else if (properties == 0x0012) { |
|
UINT8_TO_STREAM(pp, 0x02); // ADV_SCAN_IND |
|
} else if (properties == 0x0010) { |
|
UINT8_TO_STREAM(pp, 0x03); // ADV_NONCONN_IND |
|
} else { |
|
LOG(ERROR) << "Unsupported advertisement type selected:" << std::hex |
|
<< properties; |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT, 0); |
|
return; |
|
} |
|
|
|
UINT8_TO_STREAM(pp, own_address_type); |
|
UINT8_TO_STREAM(pp, peer_address_type); |
|
BDADDR_TO_STREAM(pp, peer_address); |
|
UINT8_TO_STREAM(pp, channel_map); |
|
UINT8_TO_STREAM(pp, filter_policy); |
|
|
|
SendAdvCmd( |
|
FROM_HERE, HCI_BLE_WRITE_ADV_PARAMS, param, |
|
HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS, |
|
base::Bind(&known_tx_pwr, std::move(command_complete), (int8_t)0)); |
|
} |
|
|
|
void SetAdvertisingData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, uint8_t data_length, |
|
uint8_t* data, status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
uint8_t param[HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1]; |
|
|
|
uint8_t* pp = param; |
|
memset(pp, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); |
|
UINT8_TO_STREAM(pp, data_length); |
|
ARRAY_TO_STREAM(pp, data, data_length); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_ADV_DATA, param, |
|
HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1, command_complete); |
|
} |
|
|
|
void SetScanResponseData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, |
|
uint8_t scan_response_data_length, |
|
uint8_t* scan_response_data, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
uint8_t param[HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1]; |
|
|
|
uint8_t* pp = param; |
|
memset(pp, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); |
|
UINT8_TO_STREAM(pp, scan_response_data_length); |
|
ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_SCAN_RSP_DATA, param, |
|
HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1, command_complete); |
|
} |
|
|
|
void SetRandomAddress(uint8_t handle, const RawAddress& random_address, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
uint8_t param[HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD]; |
|
|
|
uint8_t* pp = param; |
|
BDADDR_TO_STREAM(pp, random_address); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_RANDOM_ADDR, param, |
|
HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD, command_complete); |
|
} |
|
|
|
void Enable(uint8_t enable, std::vector<SetEnableData> sets, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
if (sets.size() != 1) { |
|
LOG(ERROR) << "Trying to enable multiple sets in legacy implemenetation!"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); |
|
return; |
|
} |
|
|
|
SetEnableData& set = sets[0]; |
|
if (set.max_extended_advertising_events) { |
|
command_complete.Run(HCI_ERR_ILLEGAL_PARAMETER_FMT); |
|
return; |
|
} |
|
|
|
uint8_t param[HCIC_PARAM_SIZE_WRITE_ADV_ENABLE]; |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, enable); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_ADV_ENABLE, param, |
|
HCIC_PARAM_SIZE_WRITE_ADV_ENABLE, command_complete); |
|
} |
|
|
|
void SetPeriodicAdvertisingParameters(uint8_t, uint16_t, uint16_t, uint16_t, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << "Legacy can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
void SetPeriodicAdvertisingData(uint8_t, uint8_t, uint8_t, uint8_t*, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << "Legacy can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
void SetPeriodicAdvertisingEnable(uint8_t, uint8_t, |
|
status_cb command_complete) override { |
|
LOG(INFO) << __func__ << "Legacy can't do periodic advertising"; |
|
command_complete.Run(HCI_ERR_ILLEGAL_COMMAND); |
|
} |
|
|
|
void RemoveAdvertisingSet(uint8_t handle, |
|
status_cb command_complete) override { |
|
// Legacy Advertising don't have remove method. |
|
command_complete.Run(0); |
|
} |
|
}; |
|
|
|
class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface { |
|
void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode, |
|
uint8_t* param_buf, uint8_t param_buf_len, |
|
status_cb command_complete) { |
|
btu_hcif_send_cmd_with_cb( |
|
posted_from, opcode, param_buf, param_buf_len, |
|
base::Bind(&adv_cmd_cmpl_cback, command_complete)); |
|
} |
|
|
|
void ReadInstanceCount( |
|
base::Callback<void(uint8_t /* inst_cnt*/)> cb) override { |
|
cb.Run(controller_get_interface() |
|
->get_ble_number_of_supported_advertising_sets()); |
|
} |
|
|
|
void SetAdvertisingEventObserver( |
|
AdvertisingEventObserver* observer) override { |
|
this->advertising_event_observer = observer; |
|
} |
|
|
|
void SetParameters(uint8_t handle, uint16_t properties, uint32_t adv_int_min, |
|
uint32_t adv_int_max, uint8_t channel_map, |
|
uint8_t own_address_type, |
|
const RawAddress& /* own_address */, |
|
uint8_t peer_address_type, const RawAddress& peer_address, |
|
uint8_t filter_policy, int8_t tx_power, |
|
uint8_t primary_phy, uint8_t secondary_max_skip, |
|
uint8_t secondary_phy, uint8_t advertising_sid, |
|
uint8_t scan_request_notify_enable, |
|
parameters_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
const uint16_t HCI_LE_SET_EXT_ADVERTISING_PARAM_LEN = 25; |
|
uint8_t param[HCI_LE_SET_EXT_ADVERTISING_PARAM_LEN]; |
|
memset(param, 0, HCI_LE_SET_EXT_ADVERTISING_PARAM_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
UINT16_TO_STREAM(pp, properties); |
|
UINT24_TO_STREAM(pp, adv_int_min); |
|
UINT24_TO_STREAM(pp, adv_int_max); |
|
UINT8_TO_STREAM(pp, channel_map); |
|
UINT8_TO_STREAM(pp, own_address_type); |
|
UINT8_TO_STREAM(pp, peer_address_type); |
|
BDADDR_TO_STREAM(pp, peer_address); |
|
UINT8_TO_STREAM(pp, filter_policy); |
|
INT8_TO_STREAM(pp, tx_power); |
|
UINT8_TO_STREAM(pp, primary_phy); |
|
UINT8_TO_STREAM(pp, secondary_max_skip); |
|
UINT8_TO_STREAM(pp, secondary_phy); |
|
UINT8_TO_STREAM(pp, advertising_sid); |
|
UINT8_TO_STREAM(pp, scan_request_notify_enable); |
|
|
|
btu_hcif_send_cmd_with_cb( |
|
FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_PARAM, param, |
|
HCI_LE_SET_EXT_ADVERTISING_PARAM_LEN, |
|
base::Bind(parameters_response_parser, std::move(command_complete))); |
|
} |
|
|
|
void SetAdvertisingData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, uint8_t data_length, |
|
uint8_t* data, status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
const uint16_t cmd_length = 4 + data_length; |
|
uint8_t param[cmd_length]; |
|
memset(param, 0, cmd_length); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
UINT8_TO_STREAM(pp, operation); |
|
UINT8_TO_STREAM(pp, fragment_preference); |
|
UINT8_TO_STREAM(pp, data_length); |
|
ARRAY_TO_STREAM(pp, data, data_length); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_DATA, param, cmd_length, |
|
command_complete); |
|
} |
|
|
|
void SetScanResponseData(uint8_t handle, uint8_t operation, |
|
uint8_t fragment_preference, |
|
uint8_t scan_response_data_length, |
|
uint8_t* scan_response_data, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
const uint16_t cmd_length = 4 + scan_response_data_length; |
|
uint8_t param[cmd_length]; |
|
memset(param, 0, cmd_length); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
UINT8_TO_STREAM(pp, operation); |
|
UINT8_TO_STREAM(pp, fragment_preference); |
|
UINT8_TO_STREAM(pp, scan_response_data_length); |
|
ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_SCAN_RESP, param, |
|
cmd_length, command_complete); |
|
} |
|
|
|
void SetRandomAddress(uint8_t handle, const RawAddress& random_address, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
const int LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN = 7; |
|
|
|
uint8_t param[LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN]; |
|
memset(param, 0, LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
BDADDR_TO_STREAM(pp, random_address); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_RANDOM_ADDRESS, param, |
|
LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN, command_complete); |
|
} |
|
|
|
void Enable(uint8_t enable, std::vector<SetEnableData> sets, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
/* cmd_length = header_size + num_of_of_advertiser * size_per_advertiser */ |
|
const uint16_t cmd_length = 2 + sets.size() * 4; |
|
uint8_t param[cmd_length]; |
|
memset(param, 0, cmd_length); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, enable); |
|
|
|
UINT8_TO_STREAM(pp, sets.size()); |
|
for (const SetEnableData& set : sets) { |
|
UINT8_TO_STREAM(pp, set.handle); |
|
UINT16_TO_STREAM(pp, set.duration); |
|
UINT8_TO_STREAM(pp, set.max_extended_advertising_events); |
|
} |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_ENABLE, param, cmd_length, |
|
command_complete); |
|
} |
|
|
|
void SetPeriodicAdvertisingParameters(uint8_t handle, |
|
uint16_t periodic_adv_int_min, |
|
uint16_t periodic_adv_int_max, |
|
uint16_t periodic_properties, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
const uint16_t HCI_LE_SET_PRIODIC_ADVERTISING_PARAM_LEN = 7; |
|
uint8_t param[HCI_LE_SET_PRIODIC_ADVERTISING_PARAM_LEN]; |
|
memset(param, 0, HCI_LE_SET_PRIODIC_ADVERTISING_PARAM_LEN); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
UINT16_TO_STREAM(pp, periodic_adv_int_min); |
|
UINT16_TO_STREAM(pp, periodic_adv_int_max); |
|
UINT16_TO_STREAM(pp, periodic_properties); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_PERIODIC_ADVERTISING_PARAM, param, |
|
HCI_LE_SET_PRIODIC_ADVERTISING_PARAM_LEN, command_complete); |
|
} |
|
|
|
void SetPeriodicAdvertisingData(uint8_t handle, uint8_t operation, |
|
uint8_t adv_data_length, uint8_t* adv_data, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
const uint16_t HCI_LE_SET_PRIODIC_ADVERTISING_DATA_LEN = |
|
3 + adv_data_length; |
|
uint8_t param[HCI_LE_SET_PRIODIC_ADVERTISING_DATA_LEN]; |
|
memset(param, 0, HCI_LE_SET_PRIODIC_ADVERTISING_DATA_LEN); |
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
UINT8_TO_STREAM(pp, operation); |
|
UINT8_TO_STREAM(pp, adv_data_length); |
|
ARRAY_TO_STREAM(pp, adv_data, adv_data_length); |
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_PERIODIC_ADVERTISING_DATA, param, |
|
HCI_LE_SET_PRIODIC_ADVERTISING_DATA_LEN, command_complete); |
|
} |
|
|
|
void SetPeriodicAdvertisingEnable(uint8_t enable, uint8_t handle, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
const uint16_t HCI_LE_ENABLE_PRIODIC_ADVERTISEMENT_LEN = 2; |
|
uint8_t param[HCI_LE_ENABLE_PRIODIC_ADVERTISEMENT_LEN]; |
|
memset(param, 0, HCI_LE_ENABLE_PRIODIC_ADVERTISEMENT_LEN); |
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, enable); |
|
UINT8_TO_STREAM(pp, handle); |
|
SendAdvCmd(FROM_HERE, HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE, param, |
|
HCI_LE_ENABLE_PRIODIC_ADVERTISEMENT_LEN, command_complete); |
|
} |
|
|
|
void RemoveAdvertisingSet(uint8_t handle, |
|
status_cb command_complete) override { |
|
VLOG(1) << __func__; |
|
|
|
const uint16_t cmd_length = 1; |
|
uint8_t param[cmd_length]; |
|
memset(param, 0, cmd_length); |
|
|
|
uint8_t* pp = param; |
|
UINT8_TO_STREAM(pp, handle); |
|
|
|
SendAdvCmd(FROM_HERE, HCI_LE_REMOVE_ADVERTISING_SET, param, cmd_length, |
|
command_complete); |
|
} |
|
|
|
public: |
|
void OnAdvertisingSetTerminated(uint8_t length, uint8_t* p) { |
|
VLOG(1) << __func__; |
|
LOG_ASSERT(p); |
|
uint8_t status, advertising_handle, num_completed_extended_adv_events; |
|
uint16_t conn_handle; |
|
|
|
STREAM_TO_UINT8(status, p); |
|
STREAM_TO_UINT8(advertising_handle, p); |
|
STREAM_TO_UINT16(conn_handle, p); |
|
STREAM_TO_UINT8(num_completed_extended_adv_events, p); |
|
|
|
conn_handle = conn_handle & 0x0FFF; // only 12 bits meaningful |
|
|
|
AdvertisingEventObserver* observer = this->advertising_event_observer; |
|
if (observer) |
|
observer->OnAdvertisingSetTerminated(status, advertising_handle, |
|
conn_handle, |
|
num_completed_extended_adv_events); |
|
} |
|
|
|
private: |
|
AdvertisingEventObserver* advertising_event_observer = nullptr; |
|
}; |
|
|
|
} // namespace |
|
|
|
void btm_le_on_advertising_set_terminated(uint8_t* p, uint16_t length) { |
|
if (BleAdvertiserHciInterface::Get()) { |
|
((BleAdvertiserHciExtendedImpl*)BleAdvertiserHciInterface::Get()) |
|
->OnAdvertisingSetTerminated(length, p); |
|
} |
|
} |
|
|
|
void BleAdvertiserHciInterface::Initialize() { |
|
VLOG(1) << __func__; |
|
LOG_ASSERT(instance == nullptr) << "Was already initialized."; |
|
|
|
if (controller_get_interface()->supports_ble_extended_advertising()) { |
|
LOG(INFO) << "Extended advertising will be in use"; |
|
instance = new BleAdvertiserHciExtendedImpl(); |
|
} else if (BTM_BleMaxMultiAdvInstanceCount()) { |
|
LOG(INFO) << "VSC advertising will be in use"; |
|
instance = new BleAdvertiserVscHciInterfaceImpl(); |
|
BTM_RegisterForVSEvents( |
|
BleAdvertiserVscHciInterfaceImpl::VendorSpecificEventCback, true); |
|
} else { |
|
LOG(INFO) << "Legacy advertising will be in use"; |
|
instance = new BleAdvertiserLegacyHciInterfaceImpl(); |
|
} |
|
} |
|
|
|
BleAdvertiserHciInterface* BleAdvertiserHciInterface::Get() { return instance; } |
|
|
|
void BleAdvertiserHciInterface::CleanUp() { |
|
VLOG(1) << __func__; |
|
|
|
if (BTM_BleMaxMultiAdvInstanceCount()) { |
|
BTM_RegisterForVSEvents( |
|
BleAdvertiserVscHciInterfaceImpl::VendorSpecificEventCback, false); |
|
} |
|
|
|
delete instance; |
|
instance = nullptr; |
|
}
|
|
|