1 /* 2 * Copyright 2020 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #pragma once 19 20 #include <list> 21 #include <map> 22 #include <memory> 23 #include <mutex> 24 25 #include "base/functional/bind.h" 26 #include "base/functional/callback.h" 27 #include "btm_dev.h" 28 #include "btm_iso_api.h" 29 #include "common/time_util.h" 30 #include "hci/controller_interface.h" 31 #include "hci/include/hci_layer.h" 32 #include "internal_include/bt_trace.h" 33 #include "internal_include/stack_config.h" 34 #include "main/shim/entry.h" 35 #include "main/shim/hci_layer.h" 36 #include "os/log.h" 37 #include "osi/include/allocator.h" 38 #include "stack/include/bt_hdr.h" 39 #include "stack/include/bt_types.h" 40 #include "stack/include/btm_log_history.h" 41 #include "stack/include/hci_error_code.h" 42 #include "stack/include/hcidefs.h" 43 #include "stack/include/hcimsgs.h" 44 45 namespace bluetooth { 46 namespace hci { 47 namespace iso_manager { 48 static constexpr uint8_t kIsoHeaderWithTsLen = 12; 49 static constexpr uint8_t kIsoHeaderWithoutTsLen = 8; 50 51 static constexpr uint8_t kStateFlagsNone = 0x00; 52 static constexpr uint8_t kStateFlagIsConnecting = 0x01; 53 static constexpr uint8_t kStateFlagIsConnected = 0x02; 54 static constexpr uint8_t kStateFlagHasDataPathSet = 0x04; 55 static constexpr uint8_t kStateFlagIsBroadcast = 0x10; 56 57 constexpr char kBtmLogTag[] = "ISO"; 58 59 struct iso_sync_info { 60 uint16_t seq_nb; 61 }; 62 63 struct iso_base { 64 union { 65 uint8_t cig_id; 66 uint8_t big_handle; 67 }; 68 69 struct iso_sync_info sync_info; 70 std::atomic_uint8_t state_flags; 71 uint32_t sdu_itv; 72 std::atomic_uint16_t used_credits; 73 74 struct credits_stats { 75 size_t credits_underflow_bytes = 0; 76 size_t credits_underflow_count = 0; 77 uint64_t credits_last_underflow_us = 0; 78 }; 79 80 struct event_stats { 81 size_t evt_lost_count = 0; 82 size_t seq_nb_mismatch_count = 0; 83 uint64_t evt_last_lost_us = 0; 84 }; 85 86 credits_stats cr_stats; 87 event_stats evt_stats; 88 }; 89 90 typedef iso_base iso_cis; 91 typedef iso_base iso_bis; 92 93 struct iso_impl { iso_impliso_impl94 iso_impl() { 95 iso_credits_ = shim::GetController() 96 ->GetControllerIsoBufferSize() 97 .total_num_le_packets_; 98 iso_buffer_size_ = shim::GetController() 99 ->GetControllerIsoBufferSize() 100 .le_data_packet_length_; 101 log::info("{} created, iso credits: {}, buffer size: {}.", fmt::ptr(this), 102 iso_credits_.load(), iso_buffer_size_); 103 } 104 ~iso_impliso_impl105 ~iso_impl() { log::info("{} removed.", fmt::ptr(this)); } 106 handle_register_cis_callbacksiso_impl107 void handle_register_cis_callbacks(CigCallbacks* callbacks) { 108 log::assert_that(callbacks != nullptr, "Invalid CIG callbacks"); 109 cig_callbacks_ = callbacks; 110 } 111 handle_register_big_callbacksiso_impl112 void handle_register_big_callbacks(BigCallbacks* callbacks) { 113 log::assert_that(callbacks != nullptr, "Invalid BIG callbacks"); 114 big_callbacks_ = callbacks; 115 } 116 handle_register_on_iso_traffic_active_callbackiso_impl117 void handle_register_on_iso_traffic_active_callback(void callback(bool)) { 118 log::assert_that(callback != nullptr, 119 "Invalid OnIsoTrafficActive callback"); 120 const std::lock_guard<std::mutex> lock( 121 on_iso_traffic_active_callbacks_list_mutex_); 122 on_iso_traffic_active_callbacks_list_.push_back(callback); 123 } 124 on_set_cig_paramsiso_impl125 void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream, 126 uint16_t len) { 127 uint8_t cis_cnt; 128 uint16_t conn_handle; 129 cig_create_cmpl_evt evt; 130 131 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 132 log::assert_that(len >= 3, "Invalid packet length: {}", len); 133 134 STREAM_TO_UINT8(evt.status, stream); 135 STREAM_TO_UINT8(evt.cig_id, stream); 136 STREAM_TO_UINT8(cis_cnt, stream); 137 138 uint8_t evt_code = IsCigKnown(cig_id) ? kIsoEventCigOnReconfigureCmpl 139 : kIsoEventCigOnCreateCmpl; 140 141 BTM_LogHistory( 142 kBtmLogTag, RawAddress::kEmpty, "CIG Create complete", 143 base::StringPrintf( 144 "cig_id:0x%02x, status: %s", evt.cig_id, 145 hci_status_code_text((tHCI_STATUS)(evt.status)).c_str())); 146 147 if (evt.status == HCI_SUCCESS) { 148 log::assert_that(len >= (3) + (cis_cnt * sizeof(uint16_t)), 149 "Invalid CIS count: {}", cis_cnt); 150 151 /* Remove entries for the reconfigured CIG */ 152 if (evt_code == kIsoEventCigOnReconfigureCmpl) { 153 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 154 while (cis_it != conn_hdl_to_cis_map_.cend()) { 155 if (cis_it->second->cig_id == evt.cig_id) 156 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 157 else 158 ++cis_it; 159 } 160 } 161 162 evt.conn_handles.reserve(cis_cnt); 163 for (int i = 0; i < cis_cnt; i++) { 164 STREAM_TO_UINT16(conn_handle, stream); 165 166 evt.conn_handles.push_back(conn_handle); 167 168 auto cis = std::unique_ptr<iso_cis>(new iso_cis()); 169 cis->cig_id = cig_id; 170 cis->sdu_itv = sdu_itv_mtos; 171 cis->sync_info = {.seq_nb = 0}; 172 cis->used_credits = 0; 173 cis->state_flags = kStateFlagsNone; 174 conn_hdl_to_cis_map_[conn_handle] = std::move(cis); 175 } 176 } 177 178 cig_callbacks_->OnCigEvent(evt_code, &evt); 179 180 if (evt_code == kIsoEventCigOnCreateCmpl) { 181 const std::lock_guard<std::mutex> lock( 182 on_iso_traffic_active_callbacks_list_mutex_); 183 for (auto callback : on_iso_traffic_active_callbacks_list_) { 184 callback(true); 185 } 186 } 187 } 188 create_cigiso_impl189 void create_cig(uint8_t cig_id, 190 struct iso_manager::cig_create_params cig_params) { 191 log::assert_that(!IsCigKnown(cig_id), "Invalid cig - already exists: {}", 192 cig_id); 193 194 btsnd_hcic_set_cig_params( 195 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 196 cig_params.sca, cig_params.packing, cig_params.framing, 197 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 198 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 199 base::BindOnce(&iso_impl::on_set_cig_params, weak_factory_.GetWeakPtr(), 200 cig_id, cig_params.sdu_itv_mtos)); 201 202 BTM_LogHistory( 203 kBtmLogTag, RawAddress::kEmpty, "CIG Create", 204 base::StringPrintf("cig_id:0x%02x, size: %d", cig_id, 205 static_cast<int>(cig_params.cis_cfgs.size()))); 206 } 207 reconfigure_cigiso_impl208 void reconfigure_cig(uint8_t cig_id, 209 struct iso_manager::cig_create_params cig_params) { 210 log::assert_that(IsCigKnown(cig_id), "No such cig: {}", cig_id); 211 212 btsnd_hcic_set_cig_params( 213 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 214 cig_params.sca, cig_params.packing, cig_params.framing, 215 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 216 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 217 base::BindOnce(&iso_impl::on_set_cig_params, weak_factory_.GetWeakPtr(), 218 cig_id, cig_params.sdu_itv_mtos)); 219 } 220 on_remove_cigiso_impl221 void on_remove_cig(uint8_t* stream, uint16_t len) { 222 cig_remove_cmpl_evt evt; 223 224 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 225 log::assert_that(len == 2, "Invalid packet length: {}", len); 226 227 STREAM_TO_UINT8(evt.status, stream); 228 STREAM_TO_UINT8(evt.cig_id, stream); 229 230 BTM_LogHistory( 231 kBtmLogTag, RawAddress::kEmpty, "CIG Remove complete", 232 base::StringPrintf( 233 "cig_id:0x%02x, status: %s", evt.cig_id, 234 hci_status_code_text((tHCI_STATUS)(evt.status)).c_str())); 235 236 if (evt.status == HCI_SUCCESS) { 237 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 238 while (cis_it != conn_hdl_to_cis_map_.cend()) { 239 if (cis_it->second->cig_id == evt.cig_id) 240 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 241 else 242 ++cis_it; 243 } 244 } 245 246 cig_callbacks_->OnCigEvent(kIsoEventCigOnRemoveCmpl, &evt); 247 248 { 249 const std::lock_guard<std::mutex> lock( 250 on_iso_traffic_active_callbacks_list_mutex_); 251 for (auto callback : on_iso_traffic_active_callbacks_list_) { 252 callback(false); 253 } 254 } 255 } 256 remove_cigiso_impl257 void remove_cig(uint8_t cig_id, bool force) { 258 if (!force) { 259 log::assert_that(IsCigKnown(cig_id), "No such cig: {}", cig_id); 260 } else { 261 log::warn("Forcing to remove CIG {}", cig_id); 262 } 263 264 btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig, 265 weak_factory_.GetWeakPtr())); 266 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "CIG Remove", 267 base::StringPrintf("cig_id:0x%02x (f:%d)", cig_id, force)); 268 } 269 on_status_establish_cisiso_impl270 void on_status_establish_cis( 271 struct iso_manager::cis_establish_params conn_params, uint8_t* stream, 272 uint16_t len) { 273 uint8_t status; 274 275 log::assert_that(len == 2, "Invalid packet length: {}", len); 276 277 STREAM_TO_UINT16(status, stream); 278 279 for (auto cis_param : conn_params.conn_pairs) { 280 cis_establish_cmpl_evt evt; 281 282 if (status != HCI_SUCCESS) { 283 auto cis = GetCisIfKnown(cis_param.cis_conn_handle); 284 log::assert_that(cis != nullptr, "No such cis: {}", 285 cis_param.cis_conn_handle); 286 287 evt.status = status; 288 evt.cis_conn_hdl = cis_param.cis_conn_handle; 289 evt.cig_id = cis->cig_id; 290 cis->state_flags &= ~kStateFlagIsConnecting; 291 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 292 293 BTM_LogHistory( 294 kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl], 295 "Establish CIS failed ", 296 base::StringPrintf( 297 "handle:0x%04x, status: %s", evt.cis_conn_hdl, 298 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 299 cis_hdl_to_addr.erase(evt.cis_conn_hdl); 300 } 301 } 302 } 303 establish_cisiso_impl304 void establish_cis(struct iso_manager::cis_establish_params conn_params) { 305 for (auto& el : conn_params.conn_pairs) { 306 auto cis = GetCisIfKnown(el.cis_conn_handle); 307 log::assert_that(cis, "No such cis: {}", el.cis_conn_handle); 308 log::assert_that(!(cis->state_flags & 309 (kStateFlagIsConnected | kStateFlagIsConnecting)), 310 "cis: {} is already connected or connecting flags: {}, " 311 "num of cis params: {}", 312 el.cis_conn_handle, cis->state_flags, 313 conn_params.conn_pairs.size()); 314 315 cis->state_flags |= kStateFlagIsConnecting; 316 317 tBTM_SEC_DEV_REC* p_rec = btm_find_dev_by_handle(el.acl_conn_handle); 318 if (p_rec) { 319 cis_hdl_to_addr[el.cis_conn_handle] = p_rec->ble.pseudo_addr; 320 BTM_LogHistory(kBtmLogTag, p_rec->ble.pseudo_addr, "Establish CIS", 321 base::StringPrintf("handle:0x%04x", el.acl_conn_handle)); 322 } 323 } 324 btsnd_hcic_create_cis( 325 conn_params.conn_pairs.size(), conn_params.conn_pairs.data(), 326 base::BindOnce(&iso_impl::on_status_establish_cis, 327 weak_factory_.GetWeakPtr(), conn_params)); 328 } 329 disconnect_cisiso_impl330 void disconnect_cis(uint16_t cis_handle, uint8_t reason) { 331 auto cis = GetCisIfKnown(cis_handle); 332 log::assert_that(cis, "No such cis: {}", cis_handle); 333 log::assert_that(cis->state_flags & kStateFlagIsConnected || 334 cis->state_flags & kStateFlagIsConnecting, 335 "Not connected"); 336 bluetooth::legacy::hci::GetInterface().Disconnect( 337 cis_handle, static_cast<tHCI_STATUS>(reason)); 338 339 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[cis_handle], "Disconnect CIS ", 340 base::StringPrintf( 341 "handle:0x%04x, reason:%s", cis_handle, 342 hci_reason_code_text((tHCI_REASON)(reason)).c_str())); 343 } 344 on_setup_iso_data_pathiso_impl345 void on_setup_iso_data_path(uint8_t* stream, uint16_t /* len */) { 346 uint8_t status; 347 uint16_t conn_handle; 348 349 STREAM_TO_UINT8(status, stream); 350 STREAM_TO_UINT16(conn_handle, stream); 351 352 iso_base* iso = GetIsoIfKnown(conn_handle); 353 if (iso == nullptr) { 354 /* That can happen when ACL has been disconnected while ISO patch was 355 * creating */ 356 log::warn("Invalid connection handle: {}", conn_handle); 357 return; 358 } 359 360 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle], 361 "Setup data path complete", 362 base::StringPrintf( 363 "handle:0x%04x, status:%s", conn_handle, 364 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 365 366 if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet; 367 if (iso->state_flags & kStateFlagIsBroadcast) { 368 log::assert_that(big_callbacks_ != nullptr, "Invalid BIG callbacks"); 369 big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle); 370 } else { 371 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 372 cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id); 373 } 374 } 375 setup_iso_data_pathiso_impl376 void setup_iso_data_path( 377 uint16_t conn_handle, 378 struct iso_manager::iso_data_path_params path_params) { 379 iso_base* iso = GetIsoIfKnown(conn_handle); 380 log::assert_that(iso != nullptr, "No such iso connection: {}", conn_handle); 381 382 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 383 log::assert_that(iso->state_flags & kStateFlagIsConnected, 384 "CIS not established"); 385 } 386 387 btsnd_hcic_setup_iso_data_path( 388 conn_handle, path_params.data_path_dir, path_params.data_path_id, 389 path_params.codec_id_format, path_params.codec_id_company, 390 path_params.codec_id_vendor, path_params.controller_delay, 391 std::move(path_params.codec_conf), 392 base::BindOnce(&iso_impl::on_setup_iso_data_path, 393 weak_factory_.GetWeakPtr())); 394 BTM_LogHistory( 395 kBtmLogTag, cis_hdl_to_addr[conn_handle], "Setup data path", 396 base::StringPrintf( 397 "handle:0x%04x, dir:0x%02x, path_id:0x%02x, codec_id:0x%02x", 398 conn_handle, path_params.data_path_dir, path_params.data_path_id, 399 path_params.codec_id_format)); 400 } 401 on_remove_iso_data_pathiso_impl402 void on_remove_iso_data_path(uint8_t* stream, uint16_t len) { 403 uint8_t status; 404 uint16_t conn_handle; 405 406 if (len < 3) { 407 log::warn("Malformatted packet received"); 408 return; 409 } 410 STREAM_TO_UINT8(status, stream); 411 STREAM_TO_UINT16(conn_handle, stream); 412 413 iso_base* iso = GetIsoIfKnown(conn_handle); 414 if (iso == nullptr) { 415 /* That could happen when ACL has been disconnected while removing data 416 * path */ 417 log::warn("Invalid connection handle: {}", conn_handle); 418 return; 419 } 420 421 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle], 422 "Remove data path complete", 423 base::StringPrintf( 424 "handle:0x%04x, status:%s", conn_handle, 425 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 426 427 if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet; 428 429 if (iso->state_flags & kStateFlagIsBroadcast) { 430 log::assert_that(big_callbacks_ != nullptr, "Invalid BIG callbacks"); 431 big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle); 432 } else { 433 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 434 cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id); 435 } 436 } 437 remove_iso_data_pathiso_impl438 void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { 439 iso_base* iso = GetIsoIfKnown(iso_handle); 440 log::assert_that(iso != nullptr, "No such iso connection: {}", 441 loghex(iso_handle)); 442 log::assert_that((iso->state_flags & kStateFlagHasDataPathSet) == 443 kStateFlagHasDataPathSet, 444 "Data path not set"); 445 446 btsnd_hcic_remove_iso_data_path( 447 iso_handle, data_path_dir, 448 base::BindOnce(&iso_impl::on_remove_iso_data_path, 449 weak_factory_.GetWeakPtr())); 450 451 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[iso_handle], "Remove data path", 452 base::StringPrintf("handle:0x%04x, dir:0x%02x", iso_handle, 453 data_path_dir)); 454 } 455 on_iso_link_quality_readiso_impl456 void on_iso_link_quality_read(uint8_t* stream, uint16_t len) { 457 uint8_t status; 458 uint16_t conn_handle; 459 uint32_t txUnackedPackets; 460 uint32_t txFlushedPackets; 461 uint32_t txLastSubeventPackets; 462 uint32_t retransmittedPackets; 463 uint32_t crcErrorPackets; 464 uint32_t rxUnreceivedPackets; 465 uint32_t duplicatePackets; 466 467 // 1 + 2 + 4 * 7 468 #define ISO_LINK_QUALITY_SIZE 31 469 if (len < ISO_LINK_QUALITY_SIZE) { 470 log::error("Malformated link quality format, len={}", len); 471 return; 472 } 473 474 STREAM_TO_UINT8(status, stream); 475 if (status != HCI_SUCCESS) { 476 log::error("Failed to Read ISO Link Quality, status: 0x{:x}", status); 477 return; 478 } 479 480 STREAM_TO_UINT16(conn_handle, stream); 481 482 iso_base* iso = GetIsoIfKnown(conn_handle); 483 if (iso == nullptr) { 484 /* That could happen when ACL has been disconnected while waiting on the 485 * read respose */ 486 log::warn("Invalid connection handle: {}", conn_handle); 487 return; 488 } 489 490 STREAM_TO_UINT32(txUnackedPackets, stream); 491 STREAM_TO_UINT32(txFlushedPackets, stream); 492 STREAM_TO_UINT32(txLastSubeventPackets, stream); 493 STREAM_TO_UINT32(retransmittedPackets, stream); 494 STREAM_TO_UINT32(crcErrorPackets, stream); 495 STREAM_TO_UINT32(rxUnreceivedPackets, stream); 496 STREAM_TO_UINT32(duplicatePackets, stream); 497 498 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 499 cig_callbacks_->OnIsoLinkQualityRead( 500 conn_handle, iso->cig_id, txUnackedPackets, txFlushedPackets, 501 txLastSubeventPackets, retransmittedPackets, crcErrorPackets, 502 rxUnreceivedPackets, duplicatePackets); 503 } 504 read_iso_link_qualityiso_impl505 void read_iso_link_quality(uint16_t iso_handle) { 506 iso_base* iso = GetIsoIfKnown(iso_handle); 507 if (iso == nullptr) { 508 log::error("No such iso connection: 0x{:x}", iso_handle); 509 return; 510 } 511 512 btsnd_hcic_read_iso_link_quality( 513 iso_handle, base::BindOnce(&iso_impl::on_iso_link_quality_read, 514 weak_factory_.GetWeakPtr())); 515 } 516 prepare_hci_packetiso_impl517 BT_HDR* prepare_hci_packet(uint16_t iso_handle, uint16_t seq_nb, 518 uint16_t data_len) { 519 /* Add 2 for packet seq., 2 for length */ 520 uint16_t iso_data_load_len = data_len + 4; 521 522 /* Add 2 for handle, 2 for length */ 523 uint16_t iso_full_len = iso_data_load_len + 4; 524 BT_HDR* packet = (BT_HDR*)osi_malloc(iso_full_len + sizeof(BT_HDR)); 525 packet->len = iso_full_len; 526 packet->offset = 0; 527 packet->event = MSG_STACK_TO_HC_HCI_ISO; 528 packet->layer_specific = 0; 529 530 uint8_t* packet_data = packet->data; 531 UINT16_TO_STREAM(packet_data, iso_handle); 532 UINT16_TO_STREAM(packet_data, iso_data_load_len); 533 534 UINT16_TO_STREAM(packet_data, seq_nb); 535 UINT16_TO_STREAM(packet_data, data_len); 536 537 return packet; 538 } 539 send_iso_dataiso_impl540 void send_iso_data(uint16_t iso_handle, const uint8_t* data, 541 uint16_t data_len) { 542 iso_base* iso = GetIsoIfKnown(iso_handle); 543 log::assert_that(iso != nullptr, "No such iso connection handle: {}", 544 loghex(iso_handle)); 545 546 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 547 if (!(iso->state_flags & kStateFlagIsConnected)) { 548 log::warn("Cis handle: 0x{:x} not established", iso_handle); 549 return; 550 } 551 } 552 553 if (!(iso->state_flags & kStateFlagHasDataPathSet)) { 554 log::warn("Data path not set for handle: 0x{:04x}", iso_handle); 555 return; 556 } 557 558 /* Calculate sequence number for the ISO data packet. 559 * It should be incremented by 1 every SDU Interval. 560 */ 561 uint16_t seq_nb = iso->sync_info.seq_nb; 562 iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; 563 564 if (iso_credits_ == 0 || data_len > iso_buffer_size_) { 565 iso->cr_stats.credits_underflow_bytes += data_len; 566 iso->cr_stats.credits_underflow_count++; 567 iso->cr_stats.credits_last_underflow_us = 568 bluetooth::common::time_get_os_boottime_us(); 569 570 log::warn( 571 ", dropping ISO packet, len: {}, iso credits: {}, iso handle: 0x{:x}", 572 static_cast<int>(data_len), static_cast<int>(iso_credits_), 573 iso_handle); 574 return; 575 } 576 577 iso_credits_--; 578 iso->used_credits++; 579 580 BT_HDR* packet = prepare_hci_packet(iso_handle, seq_nb, data_len); 581 memcpy(packet->data + kIsoHeaderWithoutTsLen, data, data_len); 582 auto hci = bluetooth::shim::hci_layer_get_interface(); 583 packet->event = MSG_STACK_TO_HC_HCI_ISO | 0x0001; 584 hci->transmit_downward(packet, iso_buffer_size_); 585 } 586 process_cis_est_pktiso_impl587 void process_cis_est_pkt(uint8_t len, uint8_t* data) { 588 cis_establish_cmpl_evt evt; 589 590 log::assert_that(len == 28, "Invalid packet length: {}", len); 591 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 592 593 STREAM_TO_UINT8(evt.status, data); 594 STREAM_TO_UINT16(evt.cis_conn_hdl, data); 595 596 auto cis = GetCisIfKnown(evt.cis_conn_hdl); 597 log::assert_that(cis != nullptr, "No such cis: {}", evt.cis_conn_hdl); 598 599 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl], 600 "CIS established event", 601 base::StringPrintf( 602 "cis_handle:0x%04x status:%s", evt.cis_conn_hdl, 603 hci_error_code_text((tHCI_STATUS)(evt.status)).c_str())); 604 605 STREAM_TO_UINT24(evt.cig_sync_delay, data); 606 STREAM_TO_UINT24(evt.cis_sync_delay, data); 607 STREAM_TO_UINT24(evt.trans_lat_mtos, data); 608 STREAM_TO_UINT24(evt.trans_lat_stom, data); 609 STREAM_TO_UINT8(evt.phy_mtos, data); 610 STREAM_TO_UINT8(evt.phy_stom, data); 611 STREAM_TO_UINT8(evt.nse, data); 612 STREAM_TO_UINT8(evt.bn_mtos, data); 613 STREAM_TO_UINT8(evt.bn_stom, data); 614 STREAM_TO_UINT8(evt.ft_mtos, data); 615 STREAM_TO_UINT8(evt.ft_stom, data); 616 STREAM_TO_UINT16(evt.max_pdu_mtos, data); 617 STREAM_TO_UINT16(evt.max_pdu_stom, data); 618 STREAM_TO_UINT16(evt.iso_itv, data); 619 620 if (evt.status == HCI_SUCCESS) { 621 cis->state_flags |= kStateFlagIsConnected; 622 } else { 623 cis_hdl_to_addr.erase(evt.cis_conn_hdl); 624 } 625 626 cis->state_flags &= ~kStateFlagIsConnecting; 627 628 evt.cig_id = cis->cig_id; 629 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 630 } 631 disconnection_completeiso_impl632 void disconnection_complete(uint16_t handle, uint8_t reason) { 633 /* Check if this is an ISO handle */ 634 auto cis = GetCisIfKnown(handle); 635 if (cis == nullptr) return; 636 637 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 638 639 log::info("flags: {}", cis->state_flags); 640 641 BTM_LogHistory( 642 kBtmLogTag, cis_hdl_to_addr[handle], "CIS disconnected", 643 base::StringPrintf("cis_handle:0x%04x, reason:%s", handle, 644 hci_error_code_text((tHCI_REASON)(reason)).c_str())); 645 cis_hdl_to_addr.erase(handle); 646 647 if (cis->state_flags & kStateFlagIsConnected) { 648 cis_disconnected_evt evt = { 649 .reason = reason, 650 .cig_id = cis->cig_id, 651 .cis_conn_hdl = handle, 652 }; 653 654 cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); 655 cis->state_flags &= ~kStateFlagIsConnected; 656 657 /* return used credits */ 658 iso_credits_ += cis->used_credits; 659 cis->used_credits = 0; 660 661 /* Data path is considered still valid, but can be reconfigured only once 662 * CIS is reestablished. 663 */ 664 } 665 } 666 handle_gd_num_completed_pktsiso_impl667 void handle_gd_num_completed_pkts(uint16_t handle, uint16_t credits) { 668 auto iter = conn_hdl_to_cis_map_.find(handle); 669 if (iter != conn_hdl_to_cis_map_.end()) { 670 iter->second->used_credits -= credits; 671 iso_credits_ += credits; 672 return; 673 } 674 675 iter = conn_hdl_to_bis_map_.find(handle); 676 if (iter != conn_hdl_to_bis_map_.end()) { 677 iter->second->used_credits -= credits; 678 iso_credits_ += credits; 679 } 680 } 681 process_create_big_cmpl_pktiso_impl682 void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { 683 struct big_create_cmpl_evt evt; 684 685 log::assert_that(len >= 18, "Invalid packet length: {}", len); 686 log::assert_that(big_callbacks_ != nullptr, "Invalid BIG callbacks"); 687 688 STREAM_TO_UINT8(evt.status, data); 689 STREAM_TO_UINT8(evt.big_id, data); 690 STREAM_TO_UINT24(evt.big_sync_delay, data); 691 STREAM_TO_UINT24(evt.transport_latency_big, data); 692 STREAM_TO_UINT8(evt.phy, data); 693 STREAM_TO_UINT8(evt.nse, data); 694 STREAM_TO_UINT8(evt.bn, data); 695 STREAM_TO_UINT8(evt.pto, data); 696 STREAM_TO_UINT8(evt.irc, data); 697 STREAM_TO_UINT16(evt.max_pdu, data); 698 STREAM_TO_UINT16(evt.iso_interval, data); 699 700 uint8_t num_bis; 701 STREAM_TO_UINT8(num_bis, data); 702 703 log::assert_that(num_bis != 0, "Bis count is 0"); 704 log::assert_that(len == (18 + num_bis * sizeof(uint16_t)), 705 "Invalid packet length: {}. Number of bis: {}", len, 706 num_bis); 707 708 for (auto i = 0; i < num_bis; ++i) { 709 uint16_t conn_handle; 710 STREAM_TO_UINT16(conn_handle, data); 711 evt.conn_handles.push_back(conn_handle); 712 log::info("received BIS conn_hdl {}", conn_handle); 713 714 if (evt.status == HCI_SUCCESS) { 715 auto bis = std::unique_ptr<iso_bis>(new iso_bis()); 716 bis->big_handle = evt.big_id; 717 bis->sdu_itv = last_big_create_req_sdu_itv_; 718 bis->sync_info = {.seq_nb = 0}; 719 bis->used_credits = 0; 720 bis->state_flags = kStateFlagIsBroadcast; 721 conn_hdl_to_bis_map_[conn_handle] = std::move(bis); 722 } 723 } 724 725 big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt); 726 727 { 728 const std::lock_guard<std::mutex> lock( 729 on_iso_traffic_active_callbacks_list_mutex_); 730 for (auto callbacks : on_iso_traffic_active_callbacks_list_) { 731 callbacks(true); 732 } 733 } 734 } 735 process_terminate_big_cmpl_pktiso_impl736 void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { 737 struct big_terminate_cmpl_evt evt; 738 739 log::assert_that(len == 2, "Invalid packet length: {}", len); 740 log::assert_that(big_callbacks_ != nullptr, "Invalid BIG callbacks"); 741 742 STREAM_TO_UINT8(evt.big_id, data); 743 STREAM_TO_UINT8(evt.reason, data); 744 745 bool is_known_handle = false; 746 auto bis_it = conn_hdl_to_bis_map_.cbegin(); 747 while (bis_it != conn_hdl_to_bis_map_.cend()) { 748 if (bis_it->second->big_handle == evt.big_id) { 749 bis_it = conn_hdl_to_bis_map_.erase(bis_it); 750 is_known_handle = true; 751 } else { 752 ++bis_it; 753 } 754 } 755 756 log::assert_that(is_known_handle, "No such big: {}", evt.big_id); 757 big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); 758 759 { 760 const std::lock_guard<std::mutex> lock( 761 on_iso_traffic_active_callbacks_list_mutex_); 762 for (auto callbacks : on_iso_traffic_active_callbacks_list_) { 763 callbacks(false); 764 } 765 } 766 } 767 create_bigiso_impl768 void create_big(uint8_t big_id, struct big_create_params big_params) { 769 log::assert_that(!IsBigKnown(big_id), "Invalid big - already exists: {}", 770 big_id); 771 772 if (stack_config_get_interface()->get_pts_unencrypt_broadcast()) { 773 log::info("Force create broadcst without encryption for PTS test"); 774 big_params.enc = 0; 775 big_params.enc_code = {0}; 776 } 777 778 last_big_create_req_sdu_itv_ = big_params.sdu_itv; 779 btsnd_hcic_create_big( 780 big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv, 781 big_params.max_sdu_size, big_params.max_transport_latency, 782 big_params.rtn, big_params.phy, big_params.packing, big_params.framing, 783 big_params.enc, big_params.enc_code); 784 } 785 terminate_bigiso_impl786 void terminate_big(uint8_t big_id, uint8_t reason) { 787 log::assert_that(IsBigKnown(big_id), "No such big: {}", big_id); 788 789 btsnd_hcic_term_big(big_id, reason); 790 } 791 on_iso_eventiso_impl792 void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) { 793 switch (code) { 794 case HCI_BLE_CIS_EST_EVT: 795 process_cis_est_pkt(packet_len, packet); 796 break; 797 case HCI_BLE_CREATE_BIG_CPL_EVT: 798 process_create_big_cmpl_pkt(packet_len, packet); 799 break; 800 case HCI_BLE_TERM_BIG_CPL_EVT: 801 process_terminate_big_cmpl_pkt(packet_len, packet); 802 break; 803 case HCI_BLE_CIS_REQ_EVT: 804 /* Not supported */ 805 break; 806 case HCI_BLE_BIG_SYNC_EST_EVT: 807 /* Not supported */ 808 break; 809 case HCI_BLE_BIG_SYNC_LOST_EVT: 810 /* Not supported */ 811 break; 812 default: 813 log::error("Unhandled event code {}", code); 814 } 815 } 816 handle_iso_dataiso_impl817 void handle_iso_data(BT_HDR* p_msg) { 818 const uint8_t* stream = p_msg->data; 819 cis_data_evt evt; 820 uint16_t handle, seq_nb; 821 822 if (p_msg->len <= ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) 823 ? kIsoHeaderWithTsLen 824 : kIsoHeaderWithoutTsLen)) 825 return; 826 827 log::assert_that(cig_callbacks_ != nullptr, "Invalid CIG callbacks"); 828 829 STREAM_TO_UINT16(handle, stream); 830 evt.cis_conn_hdl = HCID_GET_HANDLE(handle); 831 832 iso_base* iso = GetCisIfKnown(evt.cis_conn_hdl); 833 if (iso == nullptr) { 834 log::error(", received data for the non-registered CIS!"); 835 return; 836 } 837 838 STREAM_SKIP_UINT16(stream); 839 if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) { 840 STREAM_TO_UINT32(evt.ts, stream); 841 } else { 842 evt.ts = 0; 843 } 844 845 STREAM_TO_UINT16(seq_nb, stream); 846 847 uint16_t expected_seq_nb = iso->sync_info.seq_nb; 848 iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; 849 850 evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; 851 if (evt.evt_lost > 0) { 852 iso->evt_stats.evt_lost_count += evt.evt_lost; 853 iso->evt_stats.evt_last_lost_us = 854 bluetooth::common::time_get_os_boottime_us(); 855 856 log::warn("{} packets lost.", evt.evt_lost); 857 iso->evt_stats.seq_nb_mismatch_count++; 858 } 859 860 evt.p_msg = p_msg; 861 evt.cig_id = iso->cig_id; 862 evt.seq_nb = seq_nb; 863 cig_callbacks_->OnCisEvent(kIsoEventCisDataAvailable, &evt); 864 } 865 GetCisIfKnowniso_impl866 iso_cis* GetCisIfKnown(uint16_t cis_conn_handle) { 867 auto cis_it = conn_hdl_to_cis_map_.find(cis_conn_handle); 868 return (cis_it != conn_hdl_to_cis_map_.end()) ? cis_it->second.get() 869 : nullptr; 870 } 871 GetBisIfKnowniso_impl872 iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) { 873 auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle); 874 return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get() 875 : nullptr; 876 } 877 GetIsoIfKnowniso_impl878 iso_base* GetIsoIfKnown(uint16_t iso_handle) { 879 struct iso_base* iso = GetCisIfKnown(iso_handle); 880 return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle); 881 } 882 IsCigKnowniso_impl883 bool IsCigKnown(uint8_t cig_id) const { 884 auto const cis_it = 885 std::find_if(conn_hdl_to_cis_map_.cbegin(), conn_hdl_to_cis_map_.cend(), 886 [&cig_id](auto& kv_pair) { 887 return (kv_pair.second->cig_id == cig_id); 888 }); 889 return (cis_it != conn_hdl_to_cis_map_.cend()); 890 } 891 IsBigKnowniso_impl892 bool IsBigKnown(uint8_t big_id) const { 893 auto bis_it = 894 std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(), 895 [&big_id](auto& kv_pair) { 896 return (kv_pair.second->big_handle == big_id); 897 }); 898 return (bis_it != conn_hdl_to_bis_map_.cend()); 899 } 900 dump_credits_statsiso_impl901 static void dump_credits_stats(int fd, const iso_base::credits_stats& stats) { 902 uint64_t now_us = bluetooth::common::time_get_os_boottime_us(); 903 904 dprintf(fd, " Credits Stats:\n"); 905 dprintf(fd, " Credits underflow (count): %zu\n", 906 stats.credits_underflow_count); 907 dprintf(fd, " Credits underflow (bytes): %zu\n", 908 stats.credits_underflow_bytes); 909 dprintf( 910 fd, " Last underflow time ago (ms): %llu\n", 911 (stats.credits_last_underflow_us > 0 912 ? (unsigned long long)(now_us - stats.credits_last_underflow_us) / 913 1000 914 : 0llu)); 915 } 916 dump_event_statsiso_impl917 static void dump_event_stats(int fd, const iso_base::event_stats& stats) { 918 uint64_t now_us = bluetooth::common::time_get_os_boottime_us(); 919 920 dprintf(fd, " Event Stats:\n"); 921 dprintf(fd, " Sequence number mismatch (count): %zu\n", 922 stats.seq_nb_mismatch_count); 923 dprintf(fd, " Event lost (count): %zu\n", stats.evt_lost_count); 924 dprintf(fd, " Last event lost time ago (ms): %llu\n", 925 (stats.evt_last_lost_us > 0 926 ? (unsigned long long)(now_us - stats.evt_last_lost_us) / 1000 927 : 0llu)); 928 } 929 dumpiso_impl930 void dump(int fd) const { 931 dprintf(fd, " ----------------\n "); 932 dprintf(fd, " ISO Manager:\n"); 933 dprintf(fd, " Available credits: %d\n", iso_credits_.load()); 934 dprintf(fd, " Controller buffer size: %d\n", iso_buffer_size_); 935 dprintf(fd, " Num of ISO traffic callbacks: %lu\n", 936 static_cast<unsigned long>( 937 on_iso_traffic_active_callbacks_list_.size())); 938 dprintf(fd, " CISes:\n"); 939 for (auto const& cis_pair : conn_hdl_to_cis_map_) { 940 dprintf(fd, " CIS Connection handle: %d\n", cis_pair.first); 941 dprintf(fd, " CIG ID: %d\n", cis_pair.second->cig_id); 942 dprintf(fd, " Used Credits: %d\n", 943 cis_pair.second->used_credits.load()); 944 dprintf(fd, " SDU Interval: %d\n", cis_pair.second->sdu_itv); 945 dprintf(fd, " State Flags: 0x%02hx\n", 946 cis_pair.second->state_flags.load()); 947 dump_credits_stats(fd, cis_pair.second->cr_stats); 948 dump_event_stats(fd, cis_pair.second->evt_stats); 949 } 950 dprintf(fd, " BISes:\n"); 951 for (auto const& cis_pair : conn_hdl_to_bis_map_) { 952 dprintf(fd, " BIS Connection handle: %d\n", cis_pair.first); 953 dprintf(fd, " BIG Handle: %d\n", cis_pair.second->big_handle); 954 dprintf(fd, " Used Credits: %d\n", 955 cis_pair.second->used_credits.load()); 956 dprintf(fd, " SDU Interval: %d\n", cis_pair.second->sdu_itv); 957 dprintf(fd, " State Flags: 0x%02hx\n", 958 cis_pair.second->state_flags.load()); 959 dump_credits_stats(fd, cis_pair.second->cr_stats); 960 dump_event_stats(fd, cis_pair.second->evt_stats); 961 } 962 dprintf(fd, " ----------------\n "); 963 } 964 965 std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_; 966 std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_; 967 std::map<uint16_t, RawAddress> cis_hdl_to_addr; 968 969 std::atomic_uint16_t iso_credits_; 970 uint16_t iso_buffer_size_; 971 uint32_t last_big_create_req_sdu_itv_; 972 973 CigCallbacks* cig_callbacks_ = nullptr; 974 BigCallbacks* big_callbacks_ = nullptr; 975 std::mutex on_iso_traffic_active_callbacks_list_mutex_; 976 std::list<void (*)(bool)> on_iso_traffic_active_callbacks_list_; 977 base::WeakPtrFactory<iso_impl> weak_factory_{this}; 978 }; 979 980 } // namespace iso_manager 981 } // namespace hci 982 } // namespace bluetooth 983