1 /*
2 * Copyright 2018 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 "acl_connection_handler.h"
18
19 #include <hci/hci_packets.h>
20
21 #include "hci/address.h"
22 #include "log.h"
23
24 namespace rootcanal {
25
26 using ::bluetooth::hci::Address;
27 using ::bluetooth::hci::AddressType;
28 using ::bluetooth::hci::AddressWithType;
29
Reset(std::function<void (TaskId)> stopStream)30 void AclConnectionHandler::Reset(std::function<void(TaskId)> stopStream) {
31 // Leave no dangling periodic task.
32 for (auto& [_, sco_connection] : sco_connections_) {
33 sco_connection.StopStream(stopStream);
34 }
35
36 sco_connections_.clear();
37 acl_connections_.clear();
38 }
39
HasHandle(uint16_t handle) const40 bool AclConnectionHandler::HasHandle(uint16_t handle) const {
41 return acl_connections_.count(handle) != 0;
42 }
43
HasScoHandle(uint16_t handle) const44 bool AclConnectionHandler::HasScoHandle(uint16_t handle) const {
45 return sco_connections_.count(handle) != 0;
46 }
47
GetUnusedHandle()48 uint16_t AclConnectionHandler::GetUnusedHandle() {
49 while (HasHandle(last_handle_) || HasScoHandle(last_handle_) ||
50 isochronous_connection_handler_.HasHandle(last_handle_)) {
51 last_handle_ = (last_handle_ + 1) % kReservedHandle;
52 }
53 uint16_t unused_handle = last_handle_;
54 last_handle_ = (last_handle_ + 1) % kReservedHandle;
55 return unused_handle;
56 }
57
CreatePendingConnection(Address addr,bool authenticate_on_connect,bool allow_role_switch)58 bool AclConnectionHandler::CreatePendingConnection(Address addr,
59 bool authenticate_on_connect,
60 bool allow_role_switch) {
61 if (classic_connection_pending_) {
62 return false;
63 }
64 classic_connection_pending_ = true;
65 pending_connection_address_ = addr;
66 authenticate_pending_classic_connection_ = authenticate_on_connect;
67 pending_classic_connection_allow_role_switch_ = allow_role_switch;
68 return true;
69 }
70
HasPendingConnection(Address addr) const71 bool AclConnectionHandler::HasPendingConnection(Address addr) const {
72 return classic_connection_pending_ && pending_connection_address_ == addr;
73 }
74
AuthenticatePendingConnection() const75 bool AclConnectionHandler::AuthenticatePendingConnection() const {
76 return authenticate_pending_classic_connection_;
77 }
78
CancelPendingConnection(Address addr)79 bool AclConnectionHandler::CancelPendingConnection(Address addr) {
80 if (!classic_connection_pending_ || pending_connection_address_ != addr) {
81 return false;
82 }
83 classic_connection_pending_ = false;
84 pending_connection_address_ = Address::kEmpty;
85 pending_le_connection_resolved_address_ = AddressWithType();
86 return true;
87 }
88
CreatePendingLeConnection(AddressWithType peer,AddressWithType resolved_peer,AddressWithType local_address)89 bool AclConnectionHandler::CreatePendingLeConnection(
90 AddressWithType peer, AddressWithType resolved_peer,
91 AddressWithType local_address) {
92 for (auto pair : acl_connections_) {
93 auto connection = std::get<AclConnection>(pair);
94 if (connection.GetAddress() == peer ||
95 connection.GetResolvedAddress() == resolved_peer) {
96 LOG_INFO("%s: %s is already connected", __func__,
97 peer.ToString().c_str());
98 if (connection.GetResolvedAddress() == resolved_peer) {
99 LOG_INFO("%s: allowing a second connection with %s", __func__,
100 resolved_peer.ToString().c_str());
101 } else {
102 return false;
103 }
104 }
105 }
106 if (le_connection_pending_) {
107 LOG_INFO("%s: connection already pending", __func__);
108 return false;
109 }
110 le_connection_pending_ = true;
111 pending_le_connection_address_ = peer;
112 pending_le_connection_own_address_ = local_address;
113 pending_le_connection_resolved_address_ = resolved_peer;
114 return true;
115 }
116
HasPendingLeConnection(AddressWithType addr) const117 bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
118 return le_connection_pending_ && pending_le_connection_address_ == addr;
119 }
120
CancelPendingLeConnection(AddressWithType addr)121 bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
122 if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
123 return false;
124 }
125 le_connection_pending_ = false;
126 pending_le_connection_address_ =
127 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
128 pending_le_connection_resolved_address_ =
129 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
130 return true;
131 }
132
CreateConnection(Address addr,Address own_addr)133 uint16_t AclConnectionHandler::CreateConnection(Address addr,
134 Address own_addr) {
135 if (CancelPendingConnection(addr)) {
136 uint16_t handle = GetUnusedHandle();
137 acl_connections_.emplace(
138 handle,
139 AclConnection{
140 AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
141 AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
142 AddressWithType(), Phy::Type::BR_EDR,
143 bluetooth::hci::Role::CENTRAL});
144 return handle;
145 }
146 return kReservedHandle;
147 }
148
CreateLeConnection(AddressWithType addr,AddressWithType own_addr,bluetooth::hci::Role role)149 uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
150 AddressWithType own_addr,
151 bluetooth::hci::Role role) {
152 AddressWithType resolved_peer = pending_le_connection_resolved_address_;
153 if (CancelPendingLeConnection(addr)) {
154 uint16_t handle = GetUnusedHandle();
155 acl_connections_.emplace(handle,
156 AclConnection{addr, own_addr, resolved_peer,
157 Phy::Type::LOW_ENERGY, role});
158 return handle;
159 }
160 return kReservedHandle;
161 }
162
Disconnect(uint16_t handle,std::function<void (TaskId)> stopStream)163 bool AclConnectionHandler::Disconnect(uint16_t handle,
164 std::function<void(TaskId)> stopStream) {
165 if (HasScoHandle(handle)) {
166 sco_connections_.at(handle).StopStream(std::move(stopStream));
167 sco_connections_.erase(handle);
168 return true;
169 }
170 if (HasHandle(handle)) {
171 // It is the responsibility of the caller to remove SCO connections
172 // with connected peer first.
173 uint16_t sco_handle = GetScoHandle(GetAddress(handle).GetAddress());
174 ASSERT(!HasScoHandle(sco_handle));
175 acl_connections_.erase(handle);
176 return true;
177 }
178 return false;
179 }
180
GetHandle(AddressWithType addr) const181 uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
182 for (auto pair : acl_connections_) {
183 if (std::get<AclConnection>(pair).GetAddress() == addr) {
184 return std::get<0>(pair);
185 }
186 }
187 return kReservedHandle;
188 }
189
GetHandleOnlyAddress(bluetooth::hci::Address addr) const190 uint16_t AclConnectionHandler::GetHandleOnlyAddress(
191 bluetooth::hci::Address addr) const {
192 for (auto pair : acl_connections_) {
193 if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
194 return std::get<0>(pair);
195 }
196 }
197 return kReservedHandle;
198 }
199
GetAclConnection(uint16_t handle)200 AclConnection& AclConnectionHandler::GetAclConnection(uint16_t handle) {
201 ASSERT_LOG(HasHandle(handle), "Unknown handle %d", handle);
202 return acl_connections_.at(handle);
203 }
204
GetAddress(uint16_t handle) const205 AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
206 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
207 return acl_connections_.at(handle).GetAddress();
208 }
209
GetAddressSafe(uint16_t handle) const210 std::optional<AddressWithType> AclConnectionHandler::GetAddressSafe(
211 uint16_t handle) const {
212 return HasHandle(handle) ? acl_connections_.at(handle).GetAddress()
213 : std::optional<AddressWithType>();
214 }
215
GetScoAddress(uint16_t handle) const216 Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
217 ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
218 return sco_connections_.at(handle).GetAddress();
219 }
220
GetOwnAddress(uint16_t handle) const221 AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
222 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
223 return acl_connections_.at(handle).GetOwnAddress();
224 }
225
GetResolvedAddress(uint16_t handle) const226 AddressWithType AclConnectionHandler::GetResolvedAddress(
227 uint16_t handle) const {
228 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
229 return acl_connections_.at(handle).GetResolvedAddress();
230 }
231
Encrypt(uint16_t handle)232 void AclConnectionHandler::Encrypt(uint16_t handle) {
233 if (!HasHandle(handle)) {
234 return;
235 }
236 acl_connections_.at(handle).Encrypt();
237 }
238
IsEncrypted(uint16_t handle) const239 bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
240 if (!HasHandle(handle)) {
241 return false;
242 }
243 return acl_connections_.at(handle).IsEncrypted();
244 }
245
SetRssi(uint16_t handle,int8_t rssi)246 void AclConnectionHandler::SetRssi(uint16_t handle, int8_t rssi) {
247 if (HasHandle(handle)) {
248 acl_connections_.at(handle).SetRssi(rssi);
249 }
250 }
251
GetRssi(uint16_t handle) const252 int8_t AclConnectionHandler::GetRssi(uint16_t handle) const {
253 return HasHandle(handle) ? acl_connections_.at(handle).GetRssi() : 0;
254 }
255
GetPhyType(uint16_t handle) const256 Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
257 if (!HasHandle(handle)) {
258 return Phy::Type::BR_EDR;
259 }
260 return acl_connections_.at(handle).GetPhyType();
261 }
262
GetAclLinkPolicySettings(uint16_t handle) const263 uint16_t AclConnectionHandler::GetAclLinkPolicySettings(uint16_t handle) const {
264 return acl_connections_.at(handle).GetLinkPolicySettings();
265 };
266
SetAclLinkPolicySettings(uint16_t handle,uint16_t settings)267 void AclConnectionHandler::SetAclLinkPolicySettings(uint16_t handle,
268 uint16_t settings) {
269 acl_connections_.at(handle).SetLinkPolicySettings(settings);
270 }
271
GetAclRole(uint16_t handle) const272 bluetooth::hci::Role AclConnectionHandler::GetAclRole(uint16_t handle) const {
273 return acl_connections_.at(handle).GetRole();
274 };
275
SetAclRole(uint16_t handle,bluetooth::hci::Role role)276 void AclConnectionHandler::SetAclRole(uint16_t handle,
277 bluetooth::hci::Role role) {
278 acl_connections_.at(handle).SetRole(role);
279 }
280
281 std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
SetCigParameters(uint8_t id,uint32_t sdu_interval_m_to_s,uint32_t sdu_interval_s_to_m,bluetooth::hci::ClockAccuracy,bluetooth::hci::Packing packing,bluetooth::hci::Enable framing,uint16_t max_transport_latency_m_to_s,uint16_t max_transport_latency_s_to_m,std::vector<bluetooth::hci::CisParametersConfig> & streams)282 AclConnectionHandler::SetCigParameters(
283 uint8_t id, uint32_t sdu_interval_m_to_s, uint32_t sdu_interval_s_to_m,
284 bluetooth::hci::ClockAccuracy /* accuracy */,
285 bluetooth::hci::Packing packing, bluetooth::hci::Enable framing,
286 uint16_t max_transport_latency_m_to_s,
287 uint16_t max_transport_latency_s_to_m,
288 std::vector<bluetooth::hci::CisParametersConfig>& streams) {
289 std::vector<uint16_t> handles;
290 GroupParameters group_parameters{
291 .id = id,
292 .sdu_interval_m_to_s = sdu_interval_m_to_s,
293 .sdu_interval_s_to_m = sdu_interval_s_to_m,
294 .interleaved = packing == bluetooth::hci::Packing::INTERLEAVED,
295 .framed = framing == bluetooth::hci::Enable::ENABLED,
296 .max_transport_latency_m_to_s = max_transport_latency_m_to_s,
297 .max_transport_latency_s_to_m = max_transport_latency_s_to_m};
298 std::vector<StreamParameters> stream_parameters;
299 for (size_t i = 0; i < streams.size(); i++) {
300 auto handle = GetUnusedHandle();
301 StreamParameters a{.group_id = group_parameters.id,
302 .stream_id = streams[i].cis_id_,
303 .max_sdu_m_to_s = streams[i].max_sdu_m_to_s_,
304 .max_sdu_s_to_m = streams[i].max_sdu_s_to_m_,
305 .rtn_m_to_s = streams[i].rtn_m_to_s_,
306 .rtn_s_to_m = streams[i].rtn_s_to_m_,
307 .handle = handle};
308 handles.push_back(handle);
309 stream_parameters.push_back(std::move(a));
310 }
311
312 return isochronous_connection_handler_.SetCigParameters(
313 group_parameters, stream_parameters, std::move(handles));
314 }
315
CreatePendingCis(bluetooth::hci::CreateCisConfig config)316 void AclConnectionHandler::CreatePendingCis(
317 bluetooth::hci::CreateCisConfig config) {
318 CisHandles handles;
319 handles.cis_handle_ = config.cis_connection_handle_;
320 handles.acl_handle_ = config.acl_connection_handle_;
321 handles.remote_cis_handle_ = kReservedHandle;
322 pending_streams_.emplace_back(std::move(handles));
323 }
324
ConnectCis(uint16_t handle)325 bool AclConnectionHandler::ConnectCis(uint16_t handle) {
326 size_t position;
327 CisHandles connection;
328 for (position = 0; position < pending_streams_.size(); position++) {
329 if (handle == pending_streams_[position].cis_handle_) {
330 LOG_INFO("Found handle 0x%04hx", handle);
331 connection = pending_streams_[position];
332 pending_streams_.erase(pending_streams_.begin() + position);
333 connected_streams_.push_back(connection);
334 ASSERT(connection.cis_handle_ != kReservedHandle);
335 ASSERT(connection.acl_handle_ != kReservedHandle);
336 ASSERT(connection.remote_cis_handle_ != kReservedHandle);
337 return true;
338 }
339 }
340
341 LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
342 return false;
343 }
344
SetRemoteCisHandle(uint16_t handle,uint16_t remote_handle)345 void AclConnectionHandler::SetRemoteCisHandle(uint16_t handle,
346 uint16_t remote_handle) {
347 for (size_t position = 0; position < pending_streams_.size(); position++) {
348 if (handle == pending_streams_[position].cis_handle_) {
349 LOG_INFO("Added remote handle 0x%04hx to handle 0x%04hx", remote_handle,
350 pending_streams_[position].cis_handle_);
351 pending_streams_[position].remote_cis_handle_ = remote_handle;
352 return;
353 }
354 }
355 LOG_INFO("Couldn't find CIS connection with handle 0x%04hx", handle);
356 }
357
RejectCis(uint16_t handle)358 bool AclConnectionHandler::RejectCis(uint16_t handle) {
359 size_t position;
360 for (position = 0; position < pending_streams_.size(); position++) {
361 if (handle == pending_streams_[position].cis_handle_) {
362 pending_streams_.erase(pending_streams_.begin() + position);
363 break;
364 }
365 }
366 if (position == pending_streams_.size()) {
367 LOG_INFO("No pending connection with handle 0x%hx", handle);
368 return false;
369 }
370 return true;
371 }
372
GetPendingAclHandle(uint16_t cis_handle) const373 uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
374 size_t position;
375 uint16_t handle = 0xffff;
376 for (position = 0; position < pending_streams_.size(); position++) {
377 if (cis_handle == pending_streams_[position].cis_handle_) {
378 handle = pending_streams_[position].acl_handle_;
379 break;
380 }
381 }
382 if (position == pending_streams_.size()) {
383 LOG_INFO("No pending connection with handle 0x%hx", cis_handle);
384 }
385 return handle;
386 }
387
DisconnectCis(uint16_t cis_handle)388 bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {
389 size_t position;
390 for (position = 0; position < connected_streams_.size(); position++) {
391 if (cis_handle == connected_streams_[position].cis_handle_) {
392 connected_streams_.erase(connected_streams_.begin() + position);
393 break;
394 }
395 }
396 if (position == connected_streams_.size()) {
397 LOG_INFO("No connected stream 0x%hx", cis_handle);
398 return false;
399 }
400 return true;
401 }
402
RemoveCig(uint8_t cig_id)403 bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {
404 for (const auto& stream : connected_streams_) {
405 if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
406 cig_id) {
407 return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
408 }
409 }
410 for (const auto& stream : pending_streams_) {
411 if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
412 cig_id) {
413 return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
414 }
415 }
416 auto status = isochronous_connection_handler_.RemoveCig(cig_id);
417 if (status == bluetooth::hci::ErrorCode::SUCCESS) {
418 // Clean up?
419 }
420 return status;
421 }
422
HasPendingCisConnection(uint16_t handle) const423 bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
424 for (const auto& config : pending_streams_) {
425 if (config.cis_handle_ == handle) {
426 return true;
427 }
428 }
429 return false;
430 }
431
HasPendingCis() const432 bool AclConnectionHandler::HasPendingCis() const {
433 return !pending_streams_.empty();
434 }
435
HasConnectedCis(uint16_t handle) const436 bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
437 for (const auto& cs : connected_streams_) {
438 if (handle == cs.cis_handle_) {
439 return true;
440 }
441 }
442 return false;
443 }
444
HasCisHandle(uint16_t handle) const445 bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
446 for (const auto& cs : pending_streams_) {
447 if (handle == cs.cis_handle_) {
448 return true;
449 }
450 }
451 for (const auto& cs : connected_streams_) {
452 if (handle == cs.cis_handle_) {
453 return true;
454 }
455 }
456 return isochronous_connection_handler_.HasHandle(handle);
457 }
458
GetAclHandleForCisHandle(uint16_t cis_handle) const459 uint16_t AclConnectionHandler::GetAclHandleForCisHandle(
460 uint16_t cis_handle) const {
461 for (const auto& cs : connected_streams_) {
462 if (cis_handle == cs.cis_handle_) {
463 return cs.acl_handle_;
464 }
465 }
466 return kReservedHandle;
467 }
468
GetRemoteCisHandleForCisHandle(uint16_t cis_handle) const469 uint16_t AclConnectionHandler::GetRemoteCisHandleForCisHandle(
470 uint16_t cis_handle) const {
471 for (const auto& cs : connected_streams_) {
472 if (cis_handle == cs.cis_handle_) {
473 return cs.remote_cis_handle_;
474 }
475 }
476 return kReservedHandle;
477 }
478
GetGroupParameters(uint8_t id) const479 GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
480 return isochronous_connection_handler_.GetGroupParameters(id);
481 }
482
GetStreamParameters(uint16_t handle) const483 StreamParameters AclConnectionHandler::GetStreamParameters(
484 uint16_t handle) const {
485 return isochronous_connection_handler_.GetStreamParameters(handle);
486 }
487
CreateScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,ScoState state,ScoDatapath datapath,bool legacy)488 void AclConnectionHandler::CreateScoConnection(
489 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
490 ScoState state, ScoDatapath datapath, bool legacy) {
491 uint16_t sco_handle = GetUnusedHandle();
492 sco_connections_.emplace(
493 sco_handle, ScoConnection(addr, parameters, state, datapath, legacy));
494 }
495
HasPendingScoConnection(bluetooth::hci::Address addr) const496 bool AclConnectionHandler::HasPendingScoConnection(
497 bluetooth::hci::Address addr) const {
498 for (const auto& pair : sco_connections_) {
499 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
500 ScoState state = std::get<ScoConnection>(pair).GetState();
501 return state == SCO_STATE_PENDING ||
502 state == SCO_STATE_SENT_ESCO_CONNECTION_REQUEST ||
503 state == SCO_STATE_SENT_SCO_CONNECTION_REQUEST;
504 }
505 }
506 return false;
507 }
508
GetScoConnectionState(bluetooth::hci::Address addr) const509 ScoState AclConnectionHandler::GetScoConnectionState(
510 bluetooth::hci::Address addr) const {
511 for (const auto& pair : sco_connections_) {
512 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
513 return std::get<ScoConnection>(pair).GetState();
514 }
515 }
516 return SCO_STATE_CLOSED;
517 }
518
IsLegacyScoConnection(bluetooth::hci::Address addr) const519 bool AclConnectionHandler::IsLegacyScoConnection(
520 bluetooth::hci::Address addr) const {
521 for (const auto& pair : sco_connections_) {
522 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
523 return std::get<ScoConnection>(pair).IsLegacy();
524 }
525 }
526 return false;
527 }
528
CancelPendingScoConnection(bluetooth::hci::Address addr)529 void AclConnectionHandler::CancelPendingScoConnection(
530 bluetooth::hci::Address addr) {
531 for (auto it = sco_connections_.begin(); it != sco_connections_.end(); it++) {
532 if (std::get<ScoConnection>(*it).GetAddress() == addr) {
533 sco_connections_.erase(it);
534 return;
535 }
536 }
537 }
538
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoLinkParameters const & parameters,std::function<TaskId ()> startStream)539 bool AclConnectionHandler::AcceptPendingScoConnection(
540 bluetooth::hci::Address addr, ScoLinkParameters const& parameters,
541 std::function<TaskId()> startStream) {
542 for (auto& pair : sco_connections_) {
543 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
544 std::get<ScoConnection>(pair).SetLinkParameters(parameters);
545 std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
546 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
547 return true;
548 }
549 }
550 return false;
551 }
552
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,std::function<TaskId ()> startStream)553 bool AclConnectionHandler::AcceptPendingScoConnection(
554 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
555 std::function<TaskId()> startStream) {
556 for (auto& pair : sco_connections_) {
557 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
558 bool ok =
559 std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
560 std::get<ScoConnection>(pair).SetState(ok ? ScoState::SCO_STATE_OPENED
561 : ScoState::SCO_STATE_CLOSED);
562 if (ok) {
563 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
564 }
565 return ok;
566 }
567 }
568 return false;
569 }
570
GetScoHandle(bluetooth::hci::Address addr) const571 uint16_t AclConnectionHandler::GetScoHandle(
572 bluetooth::hci::Address addr) const {
573 for (const auto& pair : sco_connections_) {
574 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
575 return std::get<0>(pair);
576 }
577 }
578 return kReservedHandle;
579 }
580
GetScoConnectionParameters(bluetooth::hci::Address addr) const581 ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
582 bluetooth::hci::Address addr) const {
583 for (const auto& pair : sco_connections_) {
584 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
585 return std::get<ScoConnection>(pair).GetConnectionParameters();
586 }
587 }
588 return {};
589 }
590
GetScoLinkParameters(bluetooth::hci::Address addr) const591 ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(
592 bluetooth::hci::Address addr) const {
593 for (const auto& pair : sco_connections_) {
594 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
595 return std::get<ScoConnection>(pair).GetLinkParameters();
596 }
597 }
598 return {};
599 }
600
GetAclHandles() const601 std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
602 std::vector<uint16_t> keys;
603
604 for (const auto& pair : acl_connections_) {
605 keys.push_back(pair.first);
606 }
607 return keys;
608 }
609
ResetLinkTimer(uint16_t handle)610 void AclConnectionHandler::ResetLinkTimer(uint16_t handle) {
611 acl_connections_.at(handle).ResetLinkTimer();
612 }
613
614 std::chrono::steady_clock::duration
TimeUntilLinkNearExpiring(uint16_t handle) const615 AclConnectionHandler::TimeUntilLinkNearExpiring(uint16_t handle) const {
616 return acl_connections_.at(handle).TimeUntilNearExpiring();
617 }
618
IsLinkNearExpiring(uint16_t handle) const619 bool AclConnectionHandler::IsLinkNearExpiring(uint16_t handle) const {
620 return acl_connections_.at(handle).IsNearExpiring();
621 }
622
TimeUntilLinkExpired(uint16_t handle) const623 std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkExpired(
624 uint16_t handle) const {
625 return acl_connections_.at(handle).TimeUntilExpired();
626 }
627
HasLinkExpired(uint16_t handle) const628 bool AclConnectionHandler::HasLinkExpired(uint16_t handle) const {
629 return acl_connections_.at(handle).HasExpired();
630 }
631
IsRoleSwitchAllowedForPendingConnection() const632 bool AclConnectionHandler::IsRoleSwitchAllowedForPendingConnection() const {
633 return pending_classic_connection_allow_role_switch_;
634 }
635
636 } // namespace rootcanal
637