| /* |
| * Copyright 2020 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/acl_manager/classic_acl_connection.h" |
| #include "hci/acl_manager/event_checkers.h" |
| #include "hci/address.h" |
| #include "os/metrics.h" |
| |
| using bluetooth::hci::Address; |
| |
| namespace bluetooth { |
| namespace hci { |
| namespace acl_manager { |
| |
| class AclConnectionTracker : public ConnectionManagementCallbacks { |
| public: |
| AclConnectionTracker( |
| AclConnectionInterface* acl_connection_interface, const Address& address, uint16_t connection_handle) |
| : acl_connection_interface_(acl_connection_interface), address_(address), connection_handle_(connection_handle) {} |
| ~AclConnectionTracker() { |
| // If callbacks were registered, they should have been delivered. |
| ASSERT(client_callbacks_ == nullptr || queued_callbacks_.empty()); |
| } |
| void RegisterCallbacks(ConnectionManagementCallbacks* callbacks, os::Handler* handler) { |
| client_handler_ = handler; |
| client_callbacks_ = callbacks; |
| while (!queued_callbacks_.empty()) { |
| auto iter = queued_callbacks_.begin(); |
| handler->Post(std::move(*iter)); |
| queued_callbacks_.erase(iter); |
| } |
| } |
| |
| #define SAVE_OR_CALL(f, ...) \ |
| if (client_handler_ == nullptr) { \ |
| queued_callbacks_.emplace_back( \ |
| common::BindOnce(&ConnectionManagementCallbacks::f, common::Unretained(this), ##__VA_ARGS__)); \ |
| } else { \ |
| client_handler_->Post( \ |
| common::BindOnce(&ConnectionManagementCallbacks::f, common::Unretained(client_callbacks_), ##__VA_ARGS__)); \ |
| } |
| |
| void OnConnectionPacketTypeChanged(uint16_t packet_type) override { |
| SAVE_OR_CALL(OnConnectionPacketTypeChanged, packet_type) |
| } |
| void OnAuthenticationComplete(hci::ErrorCode hci_status) override { |
| SAVE_OR_CALL(OnAuthenticationComplete, hci_status) |
| } |
| void OnEncryptionChange(EncryptionEnabled enabled) override { |
| SAVE_OR_CALL(OnEncryptionChange, enabled) |
| } |
| void OnChangeConnectionLinkKeyComplete() override { |
| SAVE_OR_CALL(OnChangeConnectionLinkKeyComplete) |
| } |
| void OnReadClockOffsetComplete(uint16_t clock_offset) override { |
| SAVE_OR_CALL(OnReadClockOffsetComplete, clock_offset) |
| } |
| void OnModeChange(ErrorCode status, Mode current_mode, uint16_t interval) override { |
| SAVE_OR_CALL(OnModeChange, status, current_mode, interval) |
| } |
| void OnSniffSubrating( |
| hci::ErrorCode hci_status, |
| uint16_t maximum_transmit_latency, |
| uint16_t maximum_receive_latency, |
| uint16_t minimum_remote_timeout, |
| uint16_t minimum_local_timeout) override { |
| SAVE_OR_CALL( |
| OnSniffSubrating, |
| hci_status, |
| maximum_transmit_latency, |
| maximum_receive_latency, |
| minimum_remote_timeout, |
| minimum_local_timeout); |
| } |
| void OnQosSetupComplete(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, |
| uint32_t delay_variation) override { |
| SAVE_OR_CALL(OnQosSetupComplete, service_type, token_rate, peak_bandwidth, latency, delay_variation) |
| } |
| void OnFlowSpecificationComplete(FlowDirection flow_direction, ServiceType service_type, uint32_t token_rate, |
| uint32_t token_bucket_size, uint32_t peak_bandwidth, |
| uint32_t access_latency) override { |
| SAVE_OR_CALL(OnFlowSpecificationComplete, flow_direction, service_type, token_rate, token_bucket_size, |
| peak_bandwidth, access_latency) |
| } |
| void OnFlushOccurred() override { |
| SAVE_OR_CALL(OnFlushOccurred) |
| } |
| void OnRoleDiscoveryComplete(Role current_role) override { |
| SAVE_OR_CALL(OnRoleDiscoveryComplete, current_role) |
| } |
| void OnReadLinkPolicySettingsComplete(uint16_t link_policy_settings) override { |
| SAVE_OR_CALL(OnReadLinkPolicySettingsComplete, link_policy_settings) |
| } |
| void OnReadAutomaticFlushTimeoutComplete(uint16_t flush_timeout) override { |
| SAVE_OR_CALL(OnReadAutomaticFlushTimeoutComplete, flush_timeout) |
| } |
| void OnReadTransmitPowerLevelComplete(uint8_t transmit_power_level) override { |
| bluetooth::os::LogMetricReadTxPowerLevelResult( |
| address_, connection_handle_, static_cast<uint8_t>(ErrorCode::SUCCESS), transmit_power_level); |
| SAVE_OR_CALL(OnReadTransmitPowerLevelComplete, transmit_power_level) |
| } |
| void OnReadLinkSupervisionTimeoutComplete(uint16_t link_supervision_timeout) override { |
| SAVE_OR_CALL(OnReadLinkSupervisionTimeoutComplete, link_supervision_timeout) |
| } |
| void OnReadFailedContactCounterComplete(uint16_t failed_contact_counter) override { |
| bluetooth::os::LogMetricReadFailedContactCounterResult( |
| address_, connection_handle_, static_cast<uint8_t>(ErrorCode::SUCCESS), failed_contact_counter); |
| SAVE_OR_CALL(OnReadFailedContactCounterComplete, failed_contact_counter); |
| } |
| void OnReadLinkQualityComplete(uint8_t link_quality) override { |
| SAVE_OR_CALL(OnReadLinkQualityComplete, link_quality) |
| } |
| void OnReadAfhChannelMapComplete(AfhMode afh_mode, std::array<uint8_t, 10> afh_channel_map) override { |
| SAVE_OR_CALL(OnReadAfhChannelMapComplete, afh_mode, afh_channel_map) |
| } |
| void OnReadRssiComplete(uint8_t rssi) override { |
| bluetooth::os::LogMetricReadRssiResult( |
| address_, connection_handle_, static_cast<uint8_t>(ErrorCode::SUCCESS), rssi); |
| SAVE_OR_CALL(OnReadRssiComplete, rssi); |
| } |
| void OnReadClockComplete(uint32_t clock, uint16_t accuracy) override { |
| SAVE_OR_CALL(OnReadClockComplete, clock, accuracy) |
| } |
| void OnCentralLinkKeyComplete(KeyFlag key_flag) override { |
| SAVE_OR_CALL(OnCentralLinkKeyComplete, key_flag) |
| } |
| void OnRoleChange(hci::ErrorCode hci_status, Role new_role) override { |
| SAVE_OR_CALL(OnRoleChange, hci_status, new_role) |
| } |
| void OnReadRemoteVersionInformationComplete( |
| hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) override { |
| bluetooth::os::LogMetricRemoteVersionInfo( |
| connection_handle_, static_cast<uint8_t>(hci_status), lmp_version, manufacturer_name, sub_version); |
| SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name, sub_version); |
| } |
| void OnReadRemoteSupportedFeaturesComplete(uint64_t features) override { |
| SAVE_OR_CALL(OnReadRemoteSupportedFeaturesComplete, features); |
| } |
| void OnReadRemoteExtendedFeaturesComplete(uint8_t page_number, uint8_t max_page_number, uint64_t features) override { |
| SAVE_OR_CALL(OnReadRemoteExtendedFeaturesComplete, page_number, max_page_number, features); |
| } |
| void OnDisconnection(ErrorCode reason) { |
| SAVE_OR_CALL(OnDisconnection, reason); |
| } |
| |
| #undef SAVE_OR_CALL |
| |
| void on_role_discovery_complete(CommandCompleteView view) { |
| auto complete_view = RoleDiscoveryCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_role_discovery_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_role_discovery_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnRoleDiscoveryComplete(complete_view.GetCurrentRole()); |
| } |
| |
| void on_read_link_policy_settings_complete(CommandCompleteView view) { |
| auto complete_view = ReadLinkPolicySettingsCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_link_policy_settings_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_link_policy_settings_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadLinkPolicySettingsComplete(complete_view.GetLinkPolicySettings()); |
| } |
| |
| void on_read_automatic_flush_timeout_complete(CommandCompleteView view) { |
| auto complete_view = ReadAutomaticFlushTimeoutCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_automatic_flush_timeout_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_automatic_flush_timeout_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadAutomaticFlushTimeoutComplete(complete_view.GetFlushTimeout()); |
| } |
| |
| void on_read_transmit_power_level_complete(CommandCompleteView view) { |
| auto complete_view = ReadTransmitPowerLevelCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_transmit_power_level_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_transmit_power_level_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadTransmitPowerLevelComplete(complete_view.GetTransmitPowerLevel()); |
| } |
| |
| void on_read_link_supervision_timeout_complete(CommandCompleteView view) { |
| auto complete_view = ReadLinkSupervisionTimeoutCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_link_supervision_timeout_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_link_supervision_timeout_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadLinkSupervisionTimeoutComplete(complete_view.GetLinkSupervisionTimeout()); |
| } |
| |
| void on_read_failed_contact_counter_complete(CommandCompleteView view) { |
| auto complete_view = ReadFailedContactCounterCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_failed_contact_counter_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_failed_contact_counter_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadFailedContactCounterComplete(complete_view.GetFailedContactCounter()); |
| } |
| |
| void on_read_link_quality_complete(CommandCompleteView view) { |
| auto complete_view = ReadLinkQualityCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_link_quality_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_link_quality_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadLinkQualityComplete(complete_view.GetLinkQuality()); |
| } |
| |
| void on_read_afh_channel_map_complete(CommandCompleteView view) { |
| auto complete_view = ReadAfhChannelMapCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_afh_channel_map_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_afh_channel_map_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadAfhChannelMapComplete(complete_view.GetAfhMode(), complete_view.GetAfhChannelMap()); |
| } |
| |
| void on_read_rssi_complete(CommandCompleteView view) { |
| auto complete_view = ReadRssiCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_rssi_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_rssi_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| OnReadRssiComplete(complete_view.GetRssi()); |
| } |
| |
| void on_read_remote_version_information_status(CommandStatusView view) { |
| ASSERT_LOG(view.IsValid(), "Bad status packet!"); |
| } |
| |
| void on_read_remote_supported_features_status(CommandStatusView view) { |
| ASSERT_LOG(view.IsValid(), "Bad status packet!"); |
| } |
| |
| void on_read_remote_extended_features_status(CommandStatusView view) { |
| ASSERT_LOG(view.IsValid(), "Bad status packet!"); |
| } |
| |
| void on_read_clock_complete(CommandCompleteView view) { |
| auto complete_view = ReadClockCompleteView::Create(view); |
| if (!complete_view.IsValid()) { |
| LOG_ERROR("Received on_read_clock_complete with invalid packet"); |
| return; |
| } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { |
| auto status = complete_view.GetStatus(); |
| std::string error_code = ErrorCodeText(status); |
| LOG_ERROR("Received on_read_clock_complete with error code %s", error_code.c_str()); |
| return; |
| } |
| uint32_t clock = complete_view.GetClock(); |
| uint16_t accuracy = complete_view.GetAccuracy(); |
| OnReadClockComplete(clock, accuracy); |
| } |
| |
| AclConnectionInterface* acl_connection_interface_; |
| os::Handler* client_handler_ = nullptr; |
| ConnectionManagementCallbacks* client_callbacks_ = nullptr; |
| std::list<common::OnceClosure> queued_callbacks_; |
| Address address_; |
| uint16_t connection_handle_; |
| }; |
| |
| struct ClassicAclConnection::impl { |
| impl( |
| AclConnectionInterface* acl_connection_interface, |
| std::shared_ptr<Queue> queue, |
| const Address& address, |
| uint16_t connection_handle) |
| : tracker(acl_connection_interface, address, connection_handle), queue_(std::move(queue)) {} |
| ConnectionManagementCallbacks* GetEventCallbacks() { |
| ASSERT(!callbacks_given_); |
| callbacks_given_ = true; |
| return &tracker; |
| } |
| |
| bool callbacks_given_{false}; |
| AclConnectionTracker tracker; |
| std::shared_ptr<Queue> queue_; |
| }; |
| |
| ClassicAclConnection::ClassicAclConnection() |
| : AclConnection(), acl_connection_interface_(nullptr), address_(Address::kEmpty) {} |
| |
| ClassicAclConnection::ClassicAclConnection(std::shared_ptr<Queue> queue, |
| AclConnectionInterface* acl_connection_interface, uint16_t handle, |
| Address address) |
| : AclConnection(queue->GetUpEnd(), handle), acl_connection_interface_(acl_connection_interface), address_(address) { |
| pimpl_ = new ClassicAclConnection::impl(acl_connection_interface, std::move(queue), address, handle); |
| } |
| |
| ClassicAclConnection::~ClassicAclConnection() { |
| delete pimpl_; |
| } |
| |
| ConnectionManagementCallbacks* ClassicAclConnection::GetEventCallbacks() { |
| return pimpl_->GetEventCallbacks(); |
| } |
| |
| void ClassicAclConnection::RegisterCallbacks(ConnectionManagementCallbacks* callbacks, os::Handler* handler) { |
| return pimpl_->tracker.RegisterCallbacks(callbacks, handler); |
| } |
| |
| bool ClassicAclConnection::Disconnect(DisconnectReason reason) { |
| acl_connection_interface_->EnqueueCommand( |
| DisconnectBuilder::Create(handle_, reason), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<DisconnectStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ChangeConnectionPacketType(uint16_t packet_type) { |
| acl_connection_interface_->EnqueueCommand( |
| ChangeConnectionPacketTypeBuilder::Create(handle_, packet_type), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<ChangeConnectionPacketTypeStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::AuthenticationRequested() { |
| acl_connection_interface_->EnqueueCommand( |
| AuthenticationRequestedBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<AuthenticationRequestedStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::SetConnectionEncryption(Enable enable) { |
| acl_connection_interface_->EnqueueCommand( |
| SetConnectionEncryptionBuilder::Create(handle_, enable), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<SetConnectionEncryptionStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ChangeConnectionLinkKey() { |
| acl_connection_interface_->EnqueueCommand( |
| ChangeConnectionLinkKeyBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<ChangeConnectionLinkKeyStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadClockOffset() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadClockOffsetBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<ReadClockOffsetStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::HoldMode(uint16_t max_interval, uint16_t min_interval) { |
| acl_connection_interface_->EnqueueCommand( |
| HoldModeBuilder::Create(handle_, max_interval, min_interval), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<HoldModeStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::SniffMode(uint16_t max_interval, uint16_t min_interval, uint16_t attempt, uint16_t timeout) { |
| acl_connection_interface_->EnqueueCommand( |
| SniffModeBuilder::Create(handle_, max_interval, min_interval, attempt, timeout), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<SniffModeStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ExitSniffMode() { |
| acl_connection_interface_->EnqueueCommand( |
| ExitSniffModeBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<ExitSniffModeStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::QosSetup(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, |
| uint32_t latency, uint32_t delay_variation) { |
| acl_connection_interface_->EnqueueCommand( |
| QosSetupBuilder::Create(handle_, service_type, token_rate, peak_bandwidth, latency, delay_variation), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<QosSetupStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::RoleDiscovery() { |
| acl_connection_interface_->EnqueueCommand( |
| RoleDiscoveryBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_role_discovery_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadLinkPolicySettings() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadLinkPolicySettingsBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_link_policy_settings_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::WriteLinkPolicySettings(uint16_t link_policy_settings) { |
| acl_connection_interface_->EnqueueCommand( |
| WriteLinkPolicySettingsBuilder::Create(handle_, link_policy_settings), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<WriteLinkPolicySettingsCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::FlowSpecification(FlowDirection flow_direction, ServiceType service_type, |
| uint32_t token_rate, uint32_t token_bucket_size, uint32_t peak_bandwidth, |
| uint32_t access_latency) { |
| acl_connection_interface_->EnqueueCommand( |
| FlowSpecificationBuilder::Create(handle_, flow_direction, service_type, token_rate, token_bucket_size, |
| peak_bandwidth, access_latency), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_status<FlowSpecificationStatusView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::SniffSubrating(uint16_t maximum_latency, uint16_t minimum_remote_timeout, |
| uint16_t minimum_local_timeout) { |
| acl_connection_interface_->EnqueueCommand( |
| SniffSubratingBuilder::Create(handle_, maximum_latency, minimum_remote_timeout, minimum_local_timeout), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<SniffSubratingCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::Flush() { |
| acl_connection_interface_->EnqueueCommand( |
| FlushBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<FlushCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadAutomaticFlushTimeout() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadAutomaticFlushTimeoutBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_automatic_flush_timeout_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::WriteAutomaticFlushTimeout(uint16_t flush_timeout) { |
| acl_connection_interface_->EnqueueCommand( |
| WriteAutomaticFlushTimeoutBuilder::Create(handle_, flush_timeout), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<WriteAutomaticFlushTimeoutCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadTransmitPowerLevel(TransmitPowerLevelType type) { |
| acl_connection_interface_->EnqueueCommand( |
| ReadTransmitPowerLevelBuilder::Create(handle_, type), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_transmit_power_level_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadLinkSupervisionTimeout() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadLinkSupervisionTimeoutBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_link_supervision_timeout_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::WriteLinkSupervisionTimeout(uint16_t link_supervision_timeout) { |
| acl_connection_interface_->EnqueueCommand( |
| WriteLinkSupervisionTimeoutBuilder::Create(handle_, link_supervision_timeout), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<WriteLinkSupervisionTimeoutCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadFailedContactCounter() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadFailedContactCounterBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_failed_contact_counter_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ResetFailedContactCounter() { |
| acl_connection_interface_->EnqueueCommand( |
| ResetFailedContactCounterBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnce(&check_command_complete<ResetFailedContactCounterCompleteView>)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadLinkQuality() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadLinkQualityBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_link_quality_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadAfhChannelMap() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadAfhChannelMapBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_afh_channel_map_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadRssi() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadRssiBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_rssi_complete)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadRemoteVersionInformation() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadRemoteVersionInformationBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_remote_version_information_status)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadRemoteSupportedFeatures() { |
| acl_connection_interface_->EnqueueCommand( |
| ReadRemoteSupportedFeaturesBuilder::Create(handle_), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, |
| &AclConnectionTracker::on_read_remote_supported_features_status)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadRemoteExtendedFeatures(uint8_t page_number) { |
| acl_connection_interface_->EnqueueCommand( |
| ReadRemoteExtendedFeaturesBuilder::Create(handle_, page_number), |
| pimpl_->tracker.client_handler_->BindOnceOn( |
| &pimpl_->tracker, &AclConnectionTracker::on_read_remote_extended_features_status)); |
| return true; |
| } |
| |
| bool ClassicAclConnection::ReadClock(WhichClock which_clock) { |
| pimpl_->tracker.acl_connection_interface_->EnqueueCommand( |
| ReadClockBuilder::Create(handle_, which_clock), |
| pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_clock_complete)); |
| return true; |
| } |
| |
| } // namespace acl_manager |
| } // namespace hci |
| } // namespace bluetooth |