1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "hci/acl_manager/le_acl_connection.h"
18 #include "hci/acl_manager/le_connection_management_callbacks.h"
19 #include "os/metrics.h"
20
21 namespace bluetooth {
22 namespace hci {
23 namespace acl_manager {
24
25 class LeAclConnectionTracker : public LeConnectionManagementCallbacks {
26 public:
LeAclConnectionTracker(LeAclConnectionInterface * le_acl_connection_interface,uint16_t connection_handle)27 LeAclConnectionTracker(LeAclConnectionInterface* le_acl_connection_interface, uint16_t connection_handle)
28 : le_acl_connection_interface_(le_acl_connection_interface), connection_handle_(connection_handle) {}
~LeAclConnectionTracker()29 ~LeAclConnectionTracker() {
30 ASSERT(queued_callbacks_.empty());
31 }
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)32 void RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
33 client_handler_ = handler;
34 client_callbacks_ = callbacks;
35 while (!queued_callbacks_.empty()) {
36 auto iter = queued_callbacks_.begin();
37 handler->Post(std::move(*iter));
38 queued_callbacks_.erase(iter);
39 }
40 }
41
42 #define SAVE_OR_CALL(f, ...) \
43 if (client_handler_ == nullptr) { \
44 queued_callbacks_.emplace_back( \
45 common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(this), __VA_ARGS__)); \
46 } else { \
47 client_handler_->Post( \
48 common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(client_callbacks_), __VA_ARGS__)); \
49 }
50
OnConnectionUpdate(hci::ErrorCode hci_status,uint16_t conn_interval,uint16_t conn_latency,uint16_t supervision_timeout)51 void OnConnectionUpdate(
52 hci::ErrorCode hci_status, uint16_t conn_interval, uint16_t conn_latency, uint16_t supervision_timeout) override {
53 SAVE_OR_CALL(OnConnectionUpdate, hci_status, conn_interval, conn_latency, supervision_timeout)
54 }
55
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)56 void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override {
57 SAVE_OR_CALL(OnDataLengthChange, tx_octets, tx_time, rx_octets, rx_time)
58 }
59
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)60 void OnReadRemoteVersionInformationComplete(
61 hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) {
62 bluetooth::os::LogMetricRemoteVersionInfo(
63 connection_handle_, static_cast<uint8_t>(hci_status), lmp_version, manufacturer_name, sub_version);
64 SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name, sub_version);
65 }
OnPhyUpdate(hci::ErrorCode hci_status,uint8_t tx_phy,uint8_t rx_phy)66 void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {
67 SAVE_OR_CALL(OnPhyUpdate, hci_status, tx_phy, rx_phy);
68 }
OnLocalAddressUpdate(AddressWithType address_with_type)69 void OnLocalAddressUpdate(AddressWithType address_with_type) override {
70 SAVE_OR_CALL(OnLocalAddressUpdate, address_with_type);
71 }
72
OnDisconnection(ErrorCode reason)73 void OnDisconnection(ErrorCode reason) override {
74 SAVE_OR_CALL(OnDisconnection, reason);
75 }
76 #undef SAVE_OR_CALL
77
78 LeAclConnectionInterface* le_acl_connection_interface_;
79 os::Handler* client_handler_ = nullptr;
80 LeConnectionManagementCallbacks* client_callbacks_ = nullptr;
81 std::list<common::OnceClosure> queued_callbacks_;
82 uint16_t connection_handle_;
83 };
84
85 struct LeAclConnection::impl {
implbluetooth::hci::acl_manager::LeAclConnection::impl86 impl(LeAclConnectionInterface* le_acl_connection_interface, std::shared_ptr<Queue> queue, uint16_t connection_handle)
87 : queue_(std::move(queue)), tracker(le_acl_connection_interface, connection_handle) {}
GetEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl88 LeConnectionManagementCallbacks* GetEventCallbacks() {
89 ASSERT(!callbacks_given_);
90 callbacks_given_ = true;
91 return &tracker;
92 }
93
94 bool callbacks_given_{false};
95 std::shared_ptr<Queue> queue_;
96 LeAclConnectionTracker tracker;
97 };
98
LeAclConnection()99 LeAclConnection::LeAclConnection()
100 : AclConnection(), local_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS),
101 remote_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS) {}
102
LeAclConnection(std::shared_ptr<Queue> queue,LeAclConnectionInterface * le_acl_connection_interface,uint16_t handle,AddressWithType local_address,AddressWithType remote_address,Role role)103 LeAclConnection::LeAclConnection(
104 std::shared_ptr<Queue> queue,
105 LeAclConnectionInterface* le_acl_connection_interface,
106 uint16_t handle,
107 AddressWithType local_address,
108 AddressWithType remote_address,
109 Role role)
110 : AclConnection(queue->GetUpEnd(), handle),
111 local_address_(local_address),
112 remote_address_(remote_address),
113 role_(role) {
114 pimpl_ = new LeAclConnection::impl(le_acl_connection_interface, std::move(queue), handle);
115 }
116
~LeAclConnection()117 LeAclConnection::~LeAclConnection() {
118 delete pimpl_;
119 }
120
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)121 void LeAclConnection::RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
122 return pimpl_->tracker.RegisterCallbacks(callbacks, handler);
123 }
124
Disconnect(DisconnectReason reason)125 void LeAclConnection::Disconnect(DisconnectReason reason) {
126 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
127 DisconnectBuilder::Create(handle_, reason),
128 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
129 ASSERT(status.IsValid());
130 ASSERT(status.GetCommandOpCode() == OpCode::DISCONNECT);
131 auto disconnect_status = DisconnectStatusView::Create(status);
132 ASSERT(disconnect_status.IsValid());
133 auto error_code = disconnect_status.GetStatus();
134 if (error_code != ErrorCode::SUCCESS) {
135 LOG_INFO("Disconnect status %s", ErrorCodeText(error_code).c_str());
136 }
137 }));
138 }
139
GetEventCallbacks()140 LeConnectionManagementCallbacks* LeAclConnection::GetEventCallbacks() {
141 return pimpl_->GetEventCallbacks();
142 }
143
LeConnectionUpdate(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout,uint16_t min_ce_length,uint16_t max_ce_length)144 bool LeAclConnection::LeConnectionUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency,
145 uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length) {
146 if (!check_connection_parameters(conn_interval_min, conn_interval_max, conn_latency, supervision_timeout)) {
147 LOG_ERROR("Invalid parameter");
148 return false;
149 }
150 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
151 LeConnectionUpdateBuilder::Create(handle_, conn_interval_min, conn_interval_max, conn_latency,
152 supervision_timeout, min_ce_length, max_ce_length),
153 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
154 ASSERT(status.IsValid());
155 ASSERT(status.GetCommandOpCode() == OpCode::LE_CONNECTION_UPDATE);
156 }));
157 return true;
158 }
159
ReadRemoteVersionInformation()160 bool LeAclConnection::ReadRemoteVersionInformation() {
161 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
162 ReadRemoteVersionInformationBuilder::Create(handle_),
163 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
164 ASSERT(status.IsValid());
165 ASSERT(status.GetCommandOpCode() == OpCode::READ_REMOTE_VERSION_INFORMATION);
166 }));
167 return true;
168 }
169
check_connection_parameters(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout)170 bool LeAclConnection::check_connection_parameters(
171 uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
172 if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
173 conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A ||
174 supervision_timeout > 0x0C80) {
175 LOG_ERROR("Invalid parameter");
176 return false;
177 }
178 // The Maximum interval in milliseconds will be conn_interval_max * 1.25 ms
179 // The Timeout in milliseconds will be expected_supervision_timeout * 10 ms
180 // The Timeout in milliseconds shall be larger than (1 + Latency) * Interval_Max * 2, where Interval_Max is given in
181 // milliseconds.
182 uint32_t supervision_timeout_min = (uint32_t)(1 + conn_latency) * conn_interval_max * 2 + 1;
183 if (supervision_timeout * 8 < supervision_timeout_min || conn_interval_max < conn_interval_min) {
184 LOG_ERROR("Invalid parameter");
185 return false;
186 }
187
188 return true;
189 }
190
191 } // namespace acl_manager
192 } // namespace hci
193 } // namespace bluetooth
194