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