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 "os/log.h"
23 
24 namespace test_vendor_lib {
25 
26 using ::bluetooth::hci::Address;
27 using ::bluetooth::hci::AddressType;
28 using ::bluetooth::hci::AddressWithType;
29 
HasHandle(uint16_t handle) const30 bool AclConnectionHandler::HasHandle(uint16_t handle) const {
31   return acl_connections_.count(handle) != 0;
32 }
33 
GetUnusedHandle()34 uint16_t AclConnectionHandler::GetUnusedHandle() {
35   while (HasHandle(last_handle_) ||
36          isochronous_connection_handler_.HasHandle(last_handle_)) {
37     last_handle_ = (last_handle_ + 1) % kReservedHandle;
38   }
39   uint16_t unused_handle = last_handle_;
40   last_handle_ = (last_handle_ + 1) % kReservedHandle;
41   return unused_handle;
42 }
43 
CreatePendingConnection(Address addr,bool authenticate_on_connect)44 bool AclConnectionHandler::CreatePendingConnection(
45     Address addr, bool authenticate_on_connect) {
46   if (classic_connection_pending_) {
47     return false;
48   }
49   classic_connection_pending_ = true;
50   pending_connection_address_ = addr;
51   authenticate_pending_classic_connection_ = authenticate_on_connect;
52   return true;
53 }
54 
HasPendingConnection(Address addr) const55 bool AclConnectionHandler::HasPendingConnection(Address addr) const {
56   return classic_connection_pending_ && pending_connection_address_ == addr;
57 }
58 
AuthenticatePendingConnection() const59 bool AclConnectionHandler::AuthenticatePendingConnection() const {
60   return authenticate_pending_classic_connection_;
61 }
62 
CancelPendingConnection(Address addr)63 bool AclConnectionHandler::CancelPendingConnection(Address addr) {
64   if (!classic_connection_pending_ || pending_connection_address_ != addr) {
65     return false;
66   }
67   classic_connection_pending_ = false;
68   pending_connection_address_ = Address::kEmpty;
69   return true;
70 }
71 
CreatePendingLeConnection(AddressWithType addr)72 bool AclConnectionHandler::CreatePendingLeConnection(AddressWithType addr) {
73   bool device_connected = false;
74   for (auto pair : acl_connections_) {
75     auto connection = std::get<AclConnection>(pair);
76     if (connection.GetAddress() == addr) {
77       device_connected = true;
78     }
79   }
80   if (device_connected) {
81     LOG_INFO("%s: %s is already connected", __func__, addr.ToString().c_str());
82     return false;
83   }
84   if (le_connection_pending_) {
85     LOG_INFO("%s: connection already pending", __func__);
86     return false;
87   }
88   le_connection_pending_ = true;
89   pending_le_connection_address_ = addr;
90   return true;
91 }
92 
HasPendingLeConnection(AddressWithType addr) const93 bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
94   return le_connection_pending_ && pending_le_connection_address_ == addr;
95 }
96 
CancelPendingLeConnection(AddressWithType addr)97 bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
98   if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
99     return false;
100   }
101   le_connection_pending_ = false;
102   pending_le_connection_address_ =
103       AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
104   return true;
105 }
106 
CreateConnection(Address addr,Address own_addr)107 uint16_t AclConnectionHandler::CreateConnection(Address addr,
108                                                 Address own_addr) {
109   if (CancelPendingConnection(addr)) {
110     uint16_t handle = GetUnusedHandle();
111     acl_connections_.emplace(
112         handle,
113         AclConnection{
114             AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
115             AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
116             Phy::Type::BR_EDR});
117     return handle;
118   }
119   return kReservedHandle;
120 }
121 
CreateLeConnection(AddressWithType addr,AddressWithType own_addr)122 uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
123                                                   AddressWithType own_addr) {
124   if (CancelPendingLeConnection(addr)) {
125     uint16_t handle = GetUnusedHandle();
126     acl_connections_.emplace(
127         handle, AclConnection{addr, own_addr, Phy::Type::LOW_ENERGY});
128     return handle;
129   }
130   return kReservedHandle;
131 }
132 
Disconnect(uint16_t handle)133 bool AclConnectionHandler::Disconnect(uint16_t handle) {
134   return acl_connections_.erase(handle) > 0;
135 }
136 
GetHandle(AddressWithType addr) const137 uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
138   for (auto pair : acl_connections_) {
139     if (std::get<AclConnection>(pair).GetAddress() == addr) {
140       return std::get<0>(pair);
141     }
142   }
143   return kReservedHandle;
144 }
145 
GetHandleOnlyAddress(bluetooth::hci::Address addr) const146 uint16_t AclConnectionHandler::GetHandleOnlyAddress(
147     bluetooth::hci::Address addr) const {
148   for (auto pair : acl_connections_) {
149     if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
150       return std::get<0>(pair);
151     }
152   }
153   return kReservedHandle;
154 }
155 
GetAddress(uint16_t handle) const156 AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
157   ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
158   return acl_connections_.at(handle).GetAddress();
159 }
160 
GetOwnAddress(uint16_t handle) const161 AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
162   ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
163   return acl_connections_.at(handle).GetOwnAddress();
164 }
165 
Encrypt(uint16_t handle)166 void AclConnectionHandler::Encrypt(uint16_t handle) {
167   if (!HasHandle(handle)) {
168     return;
169   }
170   acl_connections_.at(handle).Encrypt();
171 }
172 
IsEncrypted(uint16_t handle) const173 bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
174   if (!HasHandle(handle)) {
175     return false;
176   }
177   return acl_connections_.at(handle).IsEncrypted();
178 }
179 
SetAddress(uint16_t handle,AddressWithType address)180 void AclConnectionHandler::SetAddress(uint16_t handle,
181                                       AddressWithType address) {
182   if (!HasHandle(handle)) {
183     return;
184   }
185   auto connection = acl_connections_.at(handle);
186   connection.SetAddress(address);
187 }
188 
GetPhyType(uint16_t handle) const189 Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
190   if (!HasHandle(handle)) {
191     return Phy::Type::BR_EDR;
192   }
193   return acl_connections_.at(handle).GetPhyType();
194 }
195 
196 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 accuracy,bluetooth::hci::Packing packing,bluetooth::hci::Enable framed,uint16_t max_transport_latency_m_to_s_,uint16_t max_transport_latency_s_to_m_,std::vector<bluetooth::hci::CisParametersConfig> & streams)197 AclConnectionHandler::SetCigParameters(
198     uint8_t id, uint32_t sdu_interval_m_to_s, uint32_t sdu_interval_s_to_m,
199     bluetooth::hci::ClockAccuracy accuracy, bluetooth::hci::Packing packing,
200     bluetooth::hci::Enable framed, uint16_t max_transport_latency_m_to_s_,
201     uint16_t max_transport_latency_s_to_m_,
202     std::vector<bluetooth::hci::CisParametersConfig>& streams) {
203   std::vector<uint16_t> handles;
204   GroupParameters group_parameters{
205       .id = id,
206       .sdu_interval_m_to_s = sdu_interval_m_to_s,
207       .sdu_interval_s_to_m = sdu_interval_s_to_m,
208       .interleaved = packing == bluetooth::hci::Packing::INTERLEAVED,
209       .framed = framed == bluetooth::hci::Enable::ENABLED,
210       .max_transport_latency_m_to_s = max_transport_latency_m_to_s_,
211       .max_transport_latency_s_to_m = max_transport_latency_s_to_m_};
212   std::vector<StreamParameters> stream_parameters;
213   for (size_t i = 0; i < streams.size(); i++) {
214     auto handle = GetUnusedHandle();
215     StreamParameters a{.group_id = group_parameters.id,
216                        .stream_id = streams[i].cis_id_,
217                        .max_sdu_m_to_s = streams[i].max_sdu_m_to_s_,
218                        .max_sdu_s_to_m = streams[i].max_sdu_s_to_m_,
219                        .rtn_m_to_s = streams[i].rtn_m_to_s_,
220                        .rtn_s_to_m = streams[i].rtn_s_to_m_,
221                        .handle = handle};
222     handles.push_back(handle);
223     stream_parameters.push_back(std::move(a));
224   }
225 
226   return isochronous_connection_handler_.SetCigParameters(
227       group_parameters, stream_parameters, std::move(handles));
228 }
229 
CreatePendingCis(bluetooth::hci::CreateCisConfig config)230 void AclConnectionHandler::CreatePendingCis(
231     bluetooth::hci::CreateCisConfig config) {
232   CisHandles handles;
233   handles.cis_handle_ = config.cis_connection_handle_;
234   handles.acl_handle_ = config.acl_connection_handle_;
235   handles.remote_cis_handle_ = kReservedHandle;
236   pending_streams_.emplace_back(std::move(handles));
237 }
238 
ConnectCis(uint16_t handle)239 bool AclConnectionHandler::ConnectCis(uint16_t handle) {
240   size_t position;
241   CisHandles connection;
242   for (position = 0; position < pending_streams_.size(); position++) {
243     if (handle == pending_streams_[position].cis_handle_) {
244       LOG_INFO("Found handle 0x%04hx", handle);
245       connection = pending_streams_[position];
246       pending_streams_.erase(pending_streams_.begin() + position);
247       connected_streams_.push_back(connection);
248       ASSERT(connection.cis_handle_ != kReservedHandle);
249       ASSERT(connection.acl_handle_ != kReservedHandle);
250       ASSERT(connection.remote_cis_handle_ != kReservedHandle);
251       return true;
252     }
253   }
254 
255   LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
256   return false;
257 }
258 
SetRemoteCisHandle(uint16_t handle,uint16_t remote_handle)259 void AclConnectionHandler::SetRemoteCisHandle(uint16_t handle,
260                                               uint16_t remote_handle) {
261   for (size_t position = 0; position < pending_streams_.size(); position++) {
262     if (handle == pending_streams_[position].cis_handle_) {
263       LOG_INFO("Added remote handle 0x%04hx to handle 0x%04hx", remote_handle,
264                pending_streams_[position].cis_handle_);
265       pending_streams_[position].remote_cis_handle_ = remote_handle;
266       return;
267     }
268   }
269   LOG_INFO("Couldn't find CIS connection with handle 0x%04hx", handle);
270 }
271 
RejectCis(uint16_t handle)272 bool AclConnectionHandler::RejectCis(uint16_t handle) {
273   size_t position;
274   for (position = 0; position < pending_streams_.size(); position++) {
275     if (handle == pending_streams_[position].cis_handle_) {
276       pending_streams_.erase(pending_streams_.begin() + position);
277       break;
278     }
279   }
280   if (position == pending_streams_.size()) {
281     LOG_INFO("No pending connection with handle 0x%hx", handle);
282     return false;
283   }
284   return true;
285 }
286 
GetPendingAclHandle(uint16_t cis_handle) const287 uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
288   size_t position;
289   uint16_t handle = 0xffff;
290   for (position = 0; position < pending_streams_.size(); position++) {
291     if (cis_handle == pending_streams_[position].cis_handle_) {
292       handle = pending_streams_[position].acl_handle_;
293       break;
294     }
295   }
296   if (position == pending_streams_.size()) {
297     LOG_INFO("No pending connection with handle 0x%hx", cis_handle);
298   }
299   return handle;
300 }
301 
DisconnectCis(uint16_t cis_handle)302 bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {
303   size_t position;
304   for (position = 0; position < connected_streams_.size(); position++) {
305     if (cis_handle == connected_streams_[position].cis_handle_) {
306       connected_streams_.erase(connected_streams_.begin() + position);
307       break;
308     }
309   }
310   if (position == connected_streams_.size()) {
311     LOG_INFO("No connected stream 0x%hx", cis_handle);
312     return false;
313   }
314   return true;
315 }
316 
RemoveCig(uint8_t cig_id)317 bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {
318   for (const auto& stream : connected_streams_) {
319     if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
320         cig_id) {
321       return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
322     }
323   }
324   for (const auto& stream : pending_streams_) {
325     if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
326         cig_id) {
327       return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
328     }
329   }
330   auto status = isochronous_connection_handler_.RemoveCig(cig_id);
331   if (status == bluetooth::hci::ErrorCode::SUCCESS) {
332     // Clean up?
333   }
334   return status;
335 }
336 
HasPendingCisConnection(uint16_t handle) const337 bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
338   for (const auto& config : pending_streams_) {
339     if (config.cis_handle_ == handle) {
340       return true;
341     }
342   }
343   return false;
344 }
345 
HasPendingCis() const346 bool AclConnectionHandler::HasPendingCis() const {
347   return !pending_streams_.empty();
348 }
349 
HasConnectedCis(uint16_t handle) const350 bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
351   for (const auto& cs : connected_streams_) {
352     if (handle == cs.cis_handle_) {
353       return true;
354     }
355   }
356   return false;
357 }
358 
HasCisHandle(uint16_t handle) const359 bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
360   for (const auto& cs : pending_streams_) {
361     if (handle == cs.cis_handle_) {
362       return true;
363     }
364   }
365   for (const auto& cs : connected_streams_) {
366     if (handle == cs.cis_handle_) {
367       return true;
368     }
369   }
370   return isochronous_connection_handler_.HasHandle(handle);
371 }
372 
GetAclHandleForCisHandle(uint16_t cis_handle) const373 uint16_t AclConnectionHandler::GetAclHandleForCisHandle(
374     uint16_t cis_handle) const {
375   for (const auto& cs : connected_streams_) {
376     if (cis_handle == cs.cis_handle_) {
377       return cs.acl_handle_;
378     }
379   }
380   return kReservedHandle;
381 }
382 
GetRemoteCisHandleForCisHandle(uint16_t cis_handle) const383 uint16_t AclConnectionHandler::GetRemoteCisHandleForCisHandle(
384     uint16_t cis_handle) const {
385   for (const auto& cs : connected_streams_) {
386     if (cis_handle == cs.cis_handle_) {
387       return cs.remote_cis_handle_;
388     }
389   }
390   return kReservedHandle;
391 }
392 
GetGroupParameters(uint8_t id) const393 GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
394   return isochronous_connection_handler_.GetGroupParameters(id);
395 }
396 
GetStreamParameters(uint16_t handle) const397 StreamParameters AclConnectionHandler::GetStreamParameters(
398     uint16_t handle) const {
399   return isochronous_connection_handler_.GetStreamParameters(handle);
400 }
401 
402 }  // namespace test_vendor_lib
403