355 lines
12 KiB
C++
355 lines
12 KiB
C++
|
|
/*
|
||
|
|
* Copyright 2022 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 "hci/msft.h"
|
||
|
|
|
||
|
|
#include <hardware/bt_common_types.h>
|
||
|
|
|
||
|
|
#include "hal/hci_hal.h"
|
||
|
|
#include "hci/hci_layer.h"
|
||
|
|
#include "hci/hci_packets.h"
|
||
|
|
#include "hci/vendor_specific_event_manager.h"
|
||
|
|
|
||
|
|
namespace bluetooth {
|
||
|
|
namespace hci {
|
||
|
|
|
||
|
|
// https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/
|
||
|
|
// microsoft-defined-bluetooth-hci-commands-and-events
|
||
|
|
constexpr uint8_t kMsftEventPrefixLengthMax = 0x20;
|
||
|
|
|
||
|
|
struct Msft {
|
||
|
|
// MSFT opcode needs to be configured from Bluetooth driver.
|
||
|
|
std::optional<uint16_t> opcode;
|
||
|
|
uint64_t features{0};
|
||
|
|
std::vector<uint8_t> prefix;
|
||
|
|
};
|
||
|
|
|
||
|
|
const ModuleFactory MsftExtensionManager::Factory = ModuleFactory([]() { return new MsftExtensionManager(); });
|
||
|
|
|
||
|
|
struct MsftExtensionManager::impl {
|
||
|
|
impl(Module* module) : module_(module){};
|
||
|
|
|
||
|
|
~impl() {}
|
||
|
|
|
||
|
|
void start(
|
||
|
|
os::Handler* handler,
|
||
|
|
hal::HciHal* hal,
|
||
|
|
hci::HciLayer* hci_layer,
|
||
|
|
hci::VendorSpecificEventManager* vendor_specific_event_manager) {
|
||
|
|
LOG_INFO("MsftExtensionManager start()");
|
||
|
|
module_handler_ = handler;
|
||
|
|
hal_ = hal;
|
||
|
|
hci_layer_ = hci_layer;
|
||
|
|
vendor_specific_event_manager_ = vendor_specific_event_manager;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* The MSFT opcode is assigned by Bluetooth controller vendors.
|
||
|
|
* Query the kernel/drivers to derive the MSFT opcode so that
|
||
|
|
* we can issue MSFT vendor specific commands.
|
||
|
|
*/
|
||
|
|
if (!supports_msft_extensions()) {
|
||
|
|
LOG_INFO("MSFT extension is not supported.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* The vendor prefix is required to distinguish among the vendor events
|
||
|
|
* of different vendor specifications. Read the supported features to
|
||
|
|
* derive the vendor prefix as well as other supported features.
|
||
|
|
*/
|
||
|
|
hci_layer_->EnqueueCommand(
|
||
|
|
MsftReadSupportedFeaturesBuilder::Create(static_cast<OpCode>(msft_.opcode.value())),
|
||
|
|
module_handler_->BindOnceOn(this, &impl::on_msft_read_supported_features_complete));
|
||
|
|
}
|
||
|
|
|
||
|
|
void stop() {
|
||
|
|
LOG_INFO("MsftExtensionManager stop()");
|
||
|
|
}
|
||
|
|
|
||
|
|
void handle_rssi_event(MsftRssiEventPayloadView view) {
|
||
|
|
LOG_WARN("The Microsoft MSFT_RSSI_EVENT is not supported yet.");
|
||
|
|
}
|
||
|
|
|
||
|
|
void handle_le_monitor_device_event(MsftLeMonitorDeviceEventPayloadView view) {
|
||
|
|
ASSERT(view.IsValid());
|
||
|
|
|
||
|
|
// The monitor state is 0x00 when the controller stops monitoring the device.
|
||
|
|
if (view.GetMonitorState() == 0x00 || view.GetMonitorState() == 0x01) {
|
||
|
|
AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info;
|
||
|
|
on_found_on_lost_info.advertiser_address_type = view.GetAddressType();
|
||
|
|
on_found_on_lost_info.advertiser_address = view.GetBdAddr();
|
||
|
|
on_found_on_lost_info.advertiser_state = view.GetMonitorState();
|
||
|
|
on_found_on_lost_info.monitor_handle = view.GetMonitorHandle();
|
||
|
|
scanning_callbacks_->OnTrackAdvFoundLost(on_found_on_lost_info);
|
||
|
|
} else {
|
||
|
|
LOG_WARN("The Microsoft vendor event monitor state is invalid.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void handle_msft_events(VendorSpecificEventView view) {
|
||
|
|
auto payload = view.GetPayload();
|
||
|
|
for (size_t i = 0; i < msft_.prefix.size() - 1; i++) {
|
||
|
|
if (msft_.prefix[i + 1] != payload[i]) {
|
||
|
|
LOG_WARN("The Microsoft vendor event prefix does not match.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
auto msft_view = MsftEventPayloadView::Create(
|
||
|
|
payload.GetLittleEndianSubview(msft_.prefix.size() - 1, payload.size()));
|
||
|
|
ASSERT(msft_view.IsValid());
|
||
|
|
|
||
|
|
MsftEventCode ev_code = msft_view.GetMsftEventCode();
|
||
|
|
switch (ev_code) {
|
||
|
|
case MsftEventCode::MSFT_RSSI_EVENT:
|
||
|
|
handle_rssi_event(MsftRssiEventPayloadView::Create(msft_view));
|
||
|
|
break;
|
||
|
|
case MsftEventCode::MSFT_LE_MONITOR_DEVICE_EVENT:
|
||
|
|
handle_le_monitor_device_event(MsftLeMonitorDeviceEventPayloadView::Create(msft_view));
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
LOG_WARN("Unknown MSFT event code %hhu", ev_code);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool supports_msft_extensions() {
|
||
|
|
if (msft_.opcode.has_value()) return true;
|
||
|
|
|
||
|
|
uint16_t opcode = hal_->getMsftOpcode();
|
||
|
|
if (opcode == 0) return false;
|
||
|
|
|
||
|
|
msft_.opcode = opcode;
|
||
|
|
LOG_INFO("MSFT opcode 0x%4.4x", msft_.opcode.value());
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void msft_adv_monitor_add(const MsftAdvMonitor& monitor, MsftAdvMonitorAddCallback cb) {
|
||
|
|
if (!supports_msft_extensions()) {
|
||
|
|
LOG_WARN("Disallowed as MSFT extension is not supported.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<MsftLeMonitorAdvConditionPattern> patterns;
|
||
|
|
MsftLeMonitorAdvConditionPattern pattern;
|
||
|
|
// The Microsoft Extension specifies 1 octet for the number of patterns.
|
||
|
|
// However, the max number of patters should not exceed 61.
|
||
|
|
// (255 - 1 (packet type) - 2 (OGF/OCF) - 1 (length) - 7 (MSFT command parameters)) /
|
||
|
|
// 4 (min size of a pattern) = 61
|
||
|
|
if (monitor.patterns.size() > 61) {
|
||
|
|
LOG_ERROR("Number of MSFT patterns %zu is too large", monitor.patterns.size());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (auto& p : monitor.patterns) {
|
||
|
|
pattern.ad_type_ = p.ad_type;
|
||
|
|
pattern.start_of_pattern_ = p.start_byte;
|
||
|
|
pattern.pattern_ = p.pattern;
|
||
|
|
patterns.push_back(pattern);
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_add_cb_ = cb;
|
||
|
|
hci_layer_->EnqueueCommand(
|
||
|
|
MsftLeMonitorAdvConditionPatternsBuilder::Create(
|
||
|
|
static_cast<OpCode>(msft_.opcode.value()),
|
||
|
|
monitor.rssi_threshold_high,
|
||
|
|
monitor.rssi_threshold_low,
|
||
|
|
monitor.rssi_threshold_low_time_interval,
|
||
|
|
monitor.rssi_sampling_period,
|
||
|
|
patterns),
|
||
|
|
module_handler_->BindOnceOn(this, &impl::on_msft_adv_monitor_add_complete));
|
||
|
|
}
|
||
|
|
|
||
|
|
void msft_adv_monitor_remove(uint8_t monitor_handle, MsftAdvMonitorRemoveCallback cb) {
|
||
|
|
if (!supports_msft_extensions()) {
|
||
|
|
LOG_WARN("Disallowed as MSFT extension is not supported.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_remove_cb_ = cb;
|
||
|
|
hci_layer_->EnqueueCommand(
|
||
|
|
MsftLeCancelMonitorAdvBuilder::Create(
|
||
|
|
static_cast<OpCode>(msft_.opcode.value()), monitor_handle),
|
||
|
|
module_handler_->BindOnceOn(this, &impl::on_msft_adv_monitor_remove_complete));
|
||
|
|
}
|
||
|
|
|
||
|
|
void msft_adv_monitor_enable(bool enable, MsftAdvMonitorEnableCallback cb) {
|
||
|
|
if (!supports_msft_extensions()) {
|
||
|
|
LOG_WARN("Disallowed as MSFT extension is not supported.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_enable_cb_ = cb;
|
||
|
|
hci_layer_->EnqueueCommand(
|
||
|
|
MsftLeSetAdvFilterEnableBuilder::Create(static_cast<OpCode>(msft_.opcode.value()), enable),
|
||
|
|
module_handler_->BindOnceOn(this, &impl::on_msft_adv_monitor_enable_complete));
|
||
|
|
}
|
||
|
|
|
||
|
|
void set_scanning_callback(ScanningCallback* callbacks) {
|
||
|
|
scanning_callbacks_ = callbacks;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Get the event prefix from the packet for configuring MSFT's
|
||
|
|
* Vendor Specific events. Also get the MSFT supported features.
|
||
|
|
*/
|
||
|
|
void on_msft_read_supported_features_complete(CommandCompleteView view) {
|
||
|
|
ASSERT(view.IsValid());
|
||
|
|
auto status_view = MsftReadSupportedFeaturesCommandCompleteView::Create(MsftCommandCompleteView::Create(view));
|
||
|
|
ASSERT(status_view.IsValid());
|
||
|
|
|
||
|
|
if (status_view.GetStatus() != ErrorCode::SUCCESS) {
|
||
|
|
LOG_WARN("MSFT Command complete status %s", ErrorCodeText(status_view.GetStatus()).c_str());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
MsftSubcommandOpcode sub_opcode = status_view.GetSubcommandOpcode();
|
||
|
|
if (sub_opcode != MsftSubcommandOpcode::MSFT_READ_SUPPORTED_FEATURES) {
|
||
|
|
LOG_WARN("Wrong MSFT subcommand opcode %hhu returned", sub_opcode);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_.features = status_view.GetSupportedFeatures();
|
||
|
|
|
||
|
|
// Save the vendor prefix to distinguish upcoming MSFT vendor events.
|
||
|
|
auto prefix = status_view.GetPrefix();
|
||
|
|
msft_.prefix.assign(prefix.begin(), prefix.end());
|
||
|
|
|
||
|
|
if (prefix.size() > kMsftEventPrefixLengthMax)
|
||
|
|
LOG_WARN("The MSFT prefix length %u is too large", (unsigned int)prefix.size());
|
||
|
|
|
||
|
|
LOG_INFO(
|
||
|
|
"MSFT features 0x%16.16llx prefix length %u", (unsigned long long)msft_.features, (unsigned int)prefix.size());
|
||
|
|
|
||
|
|
// We are here because Microsoft Extension is supported. Hence, register the
|
||
|
|
// first octet of the vendor prefix so that the vendor specific event manager
|
||
|
|
// can dispatch the event correctly.
|
||
|
|
// Note: registration of the first octet of the vendor prefix is sufficient
|
||
|
|
// because each vendor controller should ensure that the first octet
|
||
|
|
// is unique within the vendor's events.
|
||
|
|
vendor_specific_event_manager_->RegisterEventHandler(
|
||
|
|
static_cast<VseSubeventCode>(msft_.prefix[0]),
|
||
|
|
module_handler_->BindOn(this, &impl::handle_msft_events));
|
||
|
|
}
|
||
|
|
|
||
|
|
void on_msft_adv_monitor_add_complete(CommandCompleteView view) {
|
||
|
|
ASSERT(view.IsValid());
|
||
|
|
auto status_view =
|
||
|
|
MsftLeMonitorAdvCommandCompleteView::Create(MsftCommandCompleteView::Create(view));
|
||
|
|
ASSERT(status_view.IsValid());
|
||
|
|
|
||
|
|
MsftSubcommandOpcode sub_opcode = status_view.GetSubcommandOpcode();
|
||
|
|
if (sub_opcode != MsftSubcommandOpcode::MSFT_LE_MONITOR_ADV) {
|
||
|
|
LOG_WARN("Wrong MSFT subcommand opcode %hhu returned", sub_opcode);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_add_cb_.Run(status_view.GetMonitorHandle(), status_view.GetStatus());
|
||
|
|
}
|
||
|
|
|
||
|
|
void on_msft_adv_monitor_remove_complete(CommandCompleteView view) {
|
||
|
|
ASSERT(view.IsValid());
|
||
|
|
auto status_view =
|
||
|
|
MsftLeCancelMonitorAdvCommandCompleteView::Create(MsftCommandCompleteView::Create(view));
|
||
|
|
ASSERT(status_view.IsValid());
|
||
|
|
|
||
|
|
MsftSubcommandOpcode sub_opcode = status_view.GetSubcommandOpcode();
|
||
|
|
if (sub_opcode != MsftSubcommandOpcode::MSFT_LE_CANCEL_MONITOR_ADV) {
|
||
|
|
LOG_WARN("Wrong MSFT subcommand opcode %hhu returned", sub_opcode);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_remove_cb_.Run(status_view.GetStatus());
|
||
|
|
}
|
||
|
|
|
||
|
|
void on_msft_adv_monitor_enable_complete(CommandCompleteView view) {
|
||
|
|
ASSERT(view.IsValid());
|
||
|
|
auto status_view =
|
||
|
|
MsftLeSetAdvFilterEnableCommandCompleteView::Create(MsftCommandCompleteView::Create(view));
|
||
|
|
ASSERT(status_view.IsValid());
|
||
|
|
|
||
|
|
MsftSubcommandOpcode sub_opcode = status_view.GetSubcommandOpcode();
|
||
|
|
if (sub_opcode != MsftSubcommandOpcode::MSFT_LE_SET_ADV_FILTER_ENABLE) {
|
||
|
|
LOG_WARN("Wrong MSFT subcommand opcode %hhu returned", sub_opcode);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
msft_adv_monitor_enable_cb_.Run(status_view.GetStatus());
|
||
|
|
}
|
||
|
|
|
||
|
|
Module* module_;
|
||
|
|
os::Handler* module_handler_;
|
||
|
|
hal::HciHal* hal_;
|
||
|
|
hci::HciLayer* hci_layer_;
|
||
|
|
hci::VendorSpecificEventManager* vendor_specific_event_manager_;
|
||
|
|
Msft msft_;
|
||
|
|
MsftAdvMonitorAddCallback msft_adv_monitor_add_cb_;
|
||
|
|
MsftAdvMonitorRemoveCallback msft_adv_monitor_remove_cb_;
|
||
|
|
MsftAdvMonitorEnableCallback msft_adv_monitor_enable_cb_;
|
||
|
|
ScanningCallback* scanning_callbacks_;
|
||
|
|
};
|
||
|
|
|
||
|
|
MsftExtensionManager::MsftExtensionManager() {
|
||
|
|
LOG_INFO("MsftExtensionManager()");
|
||
|
|
pimpl_ = std::make_unique<impl>(this);
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::ListDependencies(ModuleList* list) const {
|
||
|
|
list->add<hal::HciHal>();
|
||
|
|
list->add<hci::HciLayer>();
|
||
|
|
list->add<hci::VendorSpecificEventManager>();
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::Start() {
|
||
|
|
pimpl_->start(
|
||
|
|
GetHandler(),
|
||
|
|
GetDependency<hal::HciHal>(),
|
||
|
|
GetDependency<hci::HciLayer>(),
|
||
|
|
GetDependency<hci::VendorSpecificEventManager>());
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::Stop() {
|
||
|
|
pimpl_->stop();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string MsftExtensionManager::ToString() const {
|
||
|
|
return "Microsoft Extension Manager";
|
||
|
|
}
|
||
|
|
|
||
|
|
bool MsftExtensionManager::SupportsMsftExtensions() {
|
||
|
|
return pimpl_->supports_msft_extensions();
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::MsftAdvMonitorAdd(
|
||
|
|
const MsftAdvMonitor& monitor, MsftAdvMonitorAddCallback cb) {
|
||
|
|
CallOn(pimpl_.get(), &impl::msft_adv_monitor_add, monitor, cb);
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::MsftAdvMonitorRemove(
|
||
|
|
uint8_t monitor_handle, MsftAdvMonitorRemoveCallback cb) {
|
||
|
|
CallOn(pimpl_.get(), &impl::msft_adv_monitor_remove, monitor_handle, cb);
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEnableCallback cb) {
|
||
|
|
CallOn(pimpl_.get(), &impl::msft_adv_monitor_enable, enable, cb);
|
||
|
|
}
|
||
|
|
|
||
|
|
void MsftExtensionManager::SetScanningCallback(ScanningCallback* callbacks) {
|
||
|
|
CallOn(pimpl_.get(), &impl::set_scanning_callback, callbacks);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace hci
|
||
|
|
} // namespace bluetooth
|