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
19 #include <bluetooth/log.h>
20
21 #include "hci/acl_manager/le_connection_management_callbacks.h"
22 #include "hci/event_checkers.h"
23 #include "os/metrics.h"
24
25 using bluetooth::hci::Address;
26
27 namespace bluetooth {
28 namespace hci {
29 namespace acl_manager {
30
31 class LeAclConnectionTracker : public LeConnectionManagementCallbacks {
32 public:
LeAclConnectionTracker(LeAclConnectionInterface * le_acl_connection_interface,uint16_t connection_handle)33 LeAclConnectionTracker(LeAclConnectionInterface* le_acl_connection_interface, uint16_t connection_handle)
34 : le_acl_connection_interface_(le_acl_connection_interface), connection_handle_(connection_handle) {}
~LeAclConnectionTracker()35 ~LeAclConnectionTracker() {
36 log::assert_that(queued_callbacks_.empty(), "assert failed: queued_callbacks_.empty()");
37 }
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)38 void RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
39 client_handler_ = handler;
40 client_callbacks_ = callbacks;
41 while (!queued_callbacks_.empty()) {
42 auto iter = queued_callbacks_.begin();
43 handler->Post(std::move(*iter));
44 queued_callbacks_.erase(iter);
45 }
46 }
47
48 #define SAVE_OR_CALL(f, ...) \
49 if (client_handler_ == nullptr) { \
50 queued_callbacks_.emplace_back( \
51 common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(this), __VA_ARGS__)); \
52 } else { \
53 client_handler_->Post( \
54 common::BindOnce(&LeConnectionManagementCallbacks::f, common::Unretained(client_callbacks_), __VA_ARGS__)); \
55 }
56
OnConnectionUpdate(hci::ErrorCode hci_status,uint16_t conn_interval,uint16_t conn_latency,uint16_t supervision_timeout)57 void OnConnectionUpdate(
58 hci::ErrorCode hci_status, uint16_t conn_interval, uint16_t conn_latency, uint16_t supervision_timeout) override {
59 SAVE_OR_CALL(OnConnectionUpdate, hci_status, conn_interval, conn_latency, supervision_timeout)
60 }
61
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)62 void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override {
63 SAVE_OR_CALL(OnDataLengthChange, tx_octets, tx_time, rx_octets, rx_time)
64 }
65
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)66 void OnReadRemoteVersionInformationComplete(
67 hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) {
68 bluetooth::os::LogMetricRemoteVersionInfo(
69 connection_handle_, static_cast<uint8_t>(hci_status), lmp_version, manufacturer_name, sub_version);
70 SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name, sub_version);
71 }
72
OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status,uint64_t features)73 void OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status, uint64_t features) override {
74 SAVE_OR_CALL(OnLeReadRemoteFeaturesComplete, hci_status, features);
75 }
76
OnPhyUpdate(hci::ErrorCode hci_status,uint8_t tx_phy,uint8_t rx_phy)77 void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {
78 SAVE_OR_CALL(OnPhyUpdate, hci_status, tx_phy, rx_phy);
79 }
OnLeSubrateChange(hci::ErrorCode hci_status,uint16_t subrate_factor,uint16_t peripheral_latency,uint16_t continuation_number,uint16_t supervision_timeout)80 void OnLeSubrateChange(
81 hci::ErrorCode hci_status,
82 uint16_t subrate_factor,
83 uint16_t peripheral_latency,
84 uint16_t continuation_number,
85 uint16_t supervision_timeout) override {
86 SAVE_OR_CALL(
87 OnLeSubrateChange, hci_status, subrate_factor, peripheral_latency, continuation_number, supervision_timeout);
88 }
89
OnDisconnection(ErrorCode reason)90 void OnDisconnection(ErrorCode reason) override {
91 SAVE_OR_CALL(OnDisconnection, reason);
92 }
93 #undef SAVE_OR_CALL
94
95 LeAclConnectionInterface* le_acl_connection_interface_;
96 os::Handler* client_handler_ = nullptr;
97 LeConnectionManagementCallbacks* client_callbacks_ = nullptr;
98 std::list<common::OnceClosure> queued_callbacks_;
99 const uint16_t connection_handle_;
100 };
101
102 struct LeAclConnection::impl {
implbluetooth::hci::acl_manager::LeAclConnection::impl103 impl(LeAclConnectionInterface* le_acl_connection_interface, std::shared_ptr<Queue> queue, uint16_t connection_handle)
104 : queue_(std::move(queue)), tracker(le_acl_connection_interface, connection_handle) {}
GetEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl105 LeConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks) {
106 log::assert_that(
107 !invalidate_callbacks_, "Already returned event callbacks for this connection");
108 invalidate_callbacks_ = std::move(invalidate_callbacks);
109 return &tracker;
110 }
PutEventCallbacksbluetooth::hci::acl_manager::LeAclConnection::impl111 void PutEventCallbacks() {
112 if (invalidate_callbacks_) invalidate_callbacks_(tracker.connection_handle_);
113 }
114 std::shared_ptr<Queue> queue_;
115 LeAclConnectionTracker tracker;
116 std::function<void(uint16_t)> invalidate_callbacks_;
117 };
118
LeAclConnection()119 LeAclConnection::LeAclConnection()
120 : AclConnection(),
121 remote_address_(Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS),
122 role_specific_data_(DataAsUninitializedPeripheral{}) {}
123
LeAclConnection(std::shared_ptr<Queue> queue,LeAclConnectionInterface * le_acl_connection_interface,uint16_t handle,RoleSpecificData role_specific_data,AddressWithType remote_address)124 LeAclConnection::LeAclConnection(
125 std::shared_ptr<Queue> queue,
126 LeAclConnectionInterface* le_acl_connection_interface,
127 uint16_t handle,
128 RoleSpecificData role_specific_data,
129 AddressWithType remote_address)
130 : AclConnection(queue->GetUpEnd(), handle),
131 remote_address_(remote_address),
132 role_specific_data_(role_specific_data) {
133 pimpl_ = new LeAclConnection::impl(le_acl_connection_interface, std::move(queue), handle);
134 }
135
~LeAclConnection()136 LeAclConnection::~LeAclConnection() {
137 if (pimpl_) pimpl_->PutEventCallbacks();
138 delete pimpl_;
139 }
140
GetLocalAddress() const141 AddressWithType LeAclConnection::GetLocalAddress() const {
142 return std::visit(
143 [](auto&& data) {
144 using T = std::decay_t<decltype(data)>;
145 if constexpr (std::is_same_v<T, DataAsUninitializedPeripheral>) {
146 // This case should never happen outside of acl_manager.cc, since once the connection is
147 // passed into the OnConnectSuccess callback, it should be fully initialized.
148 log::fatal("Attempted to read the local address of an uninitialized connection");
149 return AddressWithType{};
150 } else {
151 return data.local_address;
152 }
153 },
154 role_specific_data_);
155 }
156
GetRole() const157 Role LeAclConnection::GetRole() const {
158 return std::visit(
159 [](auto&& data) {
160 using T = std::decay_t<decltype(data)>;
161 if constexpr (std::is_same_v<T, DataAsCentral>) {
162 return Role::CENTRAL;
163 } else if constexpr (
164 std::is_same_v<T, DataAsPeripheral> ||
165 std::is_same_v<T, DataAsUninitializedPeripheral>) {
166 return Role::PERIPHERAL;
167 } else {
168 static_assert(!sizeof(T*), "missing case");
169 }
170 },
171 role_specific_data_);
172 }
173
GetRoleSpecificData() const174 const RoleSpecificData& LeAclConnection::GetRoleSpecificData() const {
175 return role_specific_data_;
176 }
177
RegisterCallbacks(LeConnectionManagementCallbacks * callbacks,os::Handler * handler)178 void LeAclConnection::RegisterCallbacks(LeConnectionManagementCallbacks* callbacks, os::Handler* handler) {
179 return pimpl_->tracker.RegisterCallbacks(callbacks, handler);
180 }
181
Disconnect(DisconnectReason reason)182 void LeAclConnection::Disconnect(DisconnectReason reason) {
183 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
184 DisconnectBuilder::Create(handle_, reason),
185 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
186 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
187 log::assert_that(
188 status.GetCommandOpCode() == OpCode::DISCONNECT,
189 "assert failed: status.GetCommandOpCode() == OpCode::DISCONNECT");
190 auto disconnect_status = DisconnectStatusView::Create(status);
191 log::assert_that(disconnect_status.IsValid(), "assert failed: disconnect_status.IsValid()");
192 auto error_code = disconnect_status.GetStatus();
193 if (error_code != ErrorCode::SUCCESS) {
194 log::info("Disconnect status {}", ErrorCodeText(error_code));
195 }
196 }));
197 }
198
OnLeSubrateRequestStatus(CommandStatusView status)199 void LeAclConnection::OnLeSubrateRequestStatus(CommandStatusView status) {
200 auto subrate_request_status = LeSubrateRequestStatusView::Create(status);
201 log::assert_that(
202 subrate_request_status.IsValid(), "assert failed: subrate_request_status.IsValid()");
203 auto hci_status = subrate_request_status.GetStatus();
204 if (hci_status != ErrorCode::SUCCESS) {
205 log::info("LeSubrateRequest status {}", ErrorCodeText(hci_status));
206 pimpl_->tracker.OnLeSubrateChange(hci_status, 0, 0, 0, 0);
207 }
208 }
209
LeSubrateRequest(uint16_t subrate_min,uint16_t subrate_max,uint16_t max_latency,uint16_t cont_num,uint16_t sup_tout)210 void LeAclConnection::LeSubrateRequest(
211 uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
212 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
213 LeSubrateRequestBuilder::Create(handle_, subrate_min, subrate_max, max_latency, cont_num, sup_tout),
214 pimpl_->tracker.client_handler_->BindOnceOn(this, &LeAclConnection::OnLeSubrateRequestStatus));
215 }
216
GetEventCallbacks(std::function<void (uint16_t)> invalidate_callbacks)217 LeConnectionManagementCallbacks* LeAclConnection::GetEventCallbacks(
218 std::function<void(uint16_t)> invalidate_callbacks) {
219 return pimpl_->GetEventCallbacks(std::move(invalidate_callbacks));
220 }
221
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)222 bool LeAclConnection::LeConnectionUpdate(
223 uint16_t conn_interval_min,
224 uint16_t conn_interval_max,
225 uint16_t conn_latency,
226 uint16_t supervision_timeout,
227 uint16_t min_ce_length,
228 uint16_t max_ce_length) {
229 if (!check_connection_parameters(conn_interval_min, conn_interval_max, conn_latency, supervision_timeout)) {
230 log::error("Invalid parameter");
231 return false;
232 }
233 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
234 LeConnectionUpdateBuilder::Create(
235 handle_,
236 conn_interval_min,
237 conn_interval_max,
238 conn_latency,
239 supervision_timeout,
240 min_ce_length,
241 max_ce_length),
242 pimpl_->tracker.client_handler_->BindOnce(check_status<LeConnectionUpdateStatusView>));
243 return true;
244 }
245
ReadRemoteVersionInformation()246 bool LeAclConnection::ReadRemoteVersionInformation() {
247 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
248 ReadRemoteVersionInformationBuilder::Create(handle_),
249 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
250 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
251 log::assert_that(
252 status.GetCommandOpCode() == OpCode::READ_REMOTE_VERSION_INFORMATION,
253 "assert failed: status.GetCommandOpCode() == OpCode::READ_REMOTE_VERSION_INFORMATION");
254 }));
255 return true;
256 }
257
LeReadRemoteFeatures()258 bool LeAclConnection::LeReadRemoteFeatures() {
259 pimpl_->tracker.le_acl_connection_interface_->EnqueueCommand(
260 LeReadRemoteFeaturesBuilder::Create(handle_),
261 pimpl_->tracker.client_handler_->BindOnce([](CommandStatusView status) {
262 log::assert_that(status.IsValid(), "assert failed: status.IsValid()");
263 log::assert_that(
264 status.GetCommandOpCode() == OpCode::LE_READ_REMOTE_FEATURES,
265 "assert failed: status.GetCommandOpCode() == OpCode::LE_READ_REMOTE_FEATURES");
266 }));
267 return true;
268 }
269
check_connection_parameters(uint16_t conn_interval_min,uint16_t conn_interval_max,uint16_t conn_latency,uint16_t supervision_timeout)270 bool LeAclConnection::check_connection_parameters(
271 uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
272 if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
273 conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A ||
274 supervision_timeout > 0x0C80) {
275 log::error("Invalid parameter");
276 return false;
277 }
278 // The Maximum interval in milliseconds will be conn_interval_max * 1.25 ms
279 // The Timeout in milliseconds will be expected_supervision_timeout * 10 ms
280 // The Timeout in milliseconds shall be larger than (1 + Latency) * Interval_Max * 2, where Interval_Max is given in
281 // milliseconds.
282 uint32_t supervision_timeout_min = (uint32_t)(1 + conn_latency) * conn_interval_max * 2 + 1;
283 if (supervision_timeout * 8 < supervision_timeout_min || conn_interval_max < conn_interval_min) {
284 log::error("Invalid parameter");
285 return false;
286 }
287
288 return true;
289 }
290
291 } // namespace acl_manager
292 } // namespace hci
293 } // namespace bluetooth
294