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 #include <set> 25 26 #include "base/functional/bind.h" 27 #include "base/functional/callback.h" 28 #include "base/logging.h" 29 #include "bind_helpers.h" 30 #include "btm_dev.h" 31 #include "btm_iso_api.h" 32 #include "common/time_util.h" 33 #include "device/include/controller.h" 34 #include "hci/include/hci_layer.h" 35 #include "internal_include/stack_config.h" 36 #include "osi/include/allocator.h" 37 #include "osi/include/log.h" 38 #include "stack/include/bt_hdr.h" 39 #include "stack/include/btm_log_history.h" 40 #include "stack/include/hci_error_code.h" 41 #include "stack/include/hcidefs.h" 42 43 namespace bluetooth { 44 namespace hci { 45 namespace iso_manager { 46 static constexpr uint8_t kIsoDataInTsBtHdrOffset = 0x0C; 47 static constexpr uint8_t kIsoHeaderWithTsLen = 12; 48 static constexpr uint8_t kIsoHeaderWithoutTsLen = 8; 49 50 static constexpr uint8_t kStateFlagsNone = 0x00; 51 static constexpr uint8_t kStateFlagIsConnecting = 0x01; 52 static constexpr uint8_t kStateFlagIsConnected = 0x02; 53 static constexpr uint8_t kStateFlagHasDataPathSet = 0x04; 54 static constexpr uint8_t kStateFlagIsBroadcast = 0x10; 55 56 constexpr char kBtmLogTag[] = "ISO"; 57 58 struct iso_sync_info { 59 uint32_t first_sync_ts; 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_ = controller_get_interface()->get_iso_buffer_count(); 96 iso_buffer_size_ = controller_get_interface()->get_iso_data_size(); 97 } 98 ~iso_impliso_impl99 ~iso_impl() {} 100 handle_register_cis_callbacksiso_impl101 void handle_register_cis_callbacks(CigCallbacks* callbacks) { 102 LOG_ASSERT(callbacks != nullptr) << "Invalid CIG callbacks"; 103 cig_callbacks_ = callbacks; 104 } 105 handle_register_big_callbacksiso_impl106 void handle_register_big_callbacks(BigCallbacks* callbacks) { 107 LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks"; 108 big_callbacks_ = callbacks; 109 } 110 handle_register_on_iso_traffic_active_callbackiso_impl111 void handle_register_on_iso_traffic_active_callback(void callback(bool)) { 112 LOG_ASSERT(callback != nullptr) << "Invalid OnIsoTrafficActive callback"; 113 const std::lock_guard<std::mutex> lock( 114 on_iso_traffic_active_callbacks_list_mutex_); 115 on_iso_traffic_active_callbacks_list_.push_back(callback); 116 } 117 on_set_cig_paramsiso_impl118 void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream, 119 uint16_t len) { 120 uint8_t cis_cnt; 121 uint16_t conn_handle; 122 cig_create_cmpl_evt evt; 123 124 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 125 LOG_ASSERT(len >= 3) << "Invalid packet length: " << +len; 126 127 STREAM_TO_UINT8(evt.status, stream); 128 STREAM_TO_UINT8(evt.cig_id, stream); 129 STREAM_TO_UINT8(cis_cnt, stream); 130 131 uint8_t evt_code = IsCigKnown(cig_id) ? kIsoEventCigOnReconfigureCmpl 132 : kIsoEventCigOnCreateCmpl; 133 134 BTM_LogHistory( 135 kBtmLogTag, RawAddress::kEmpty, "CIG Create complete", 136 base::StringPrintf( 137 "cig_id:0x%02x, status: %s", evt.cig_id, 138 hci_status_code_text((tHCI_STATUS)(evt.status)).c_str())); 139 140 if (evt.status == HCI_SUCCESS) { 141 LOG_ASSERT(len >= (3) + (cis_cnt * sizeof(uint16_t))) 142 << "Invalid CIS count: " << +cis_cnt; 143 144 /* Remove entries for the reconfigured CIG */ 145 if (evt_code == kIsoEventCigOnReconfigureCmpl) { 146 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 147 while (cis_it != conn_hdl_to_cis_map_.cend()) { 148 if (cis_it->second->cig_id == evt.cig_id) 149 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 150 else 151 ++cis_it; 152 } 153 } 154 155 evt.conn_handles.reserve(cis_cnt); 156 for (int i = 0; i < cis_cnt; i++) { 157 STREAM_TO_UINT16(conn_handle, stream); 158 159 evt.conn_handles.push_back(conn_handle); 160 161 auto cis = std::unique_ptr<iso_cis>(new iso_cis()); 162 cis->cig_id = cig_id; 163 cis->sdu_itv = sdu_itv_mtos; 164 cis->sync_info = {.first_sync_ts = 0, .seq_nb = 0}; 165 cis->used_credits = 0; 166 cis->state_flags = kStateFlagsNone; 167 conn_hdl_to_cis_map_[conn_handle] = std::move(cis); 168 } 169 } 170 171 cig_callbacks_->OnCigEvent(evt_code, &evt); 172 173 if (evt_code == kIsoEventCigOnCreateCmpl) { 174 const std::lock_guard<std::mutex> lock( 175 on_iso_traffic_active_callbacks_list_mutex_); 176 for (auto callback : on_iso_traffic_active_callbacks_list_) { 177 callback(true); 178 } 179 } 180 } 181 create_cigiso_impl182 void create_cig(uint8_t cig_id, 183 struct iso_manager::cig_create_params cig_params) { 184 LOG_ASSERT(!IsCigKnown(cig_id)) 185 << "Invalid cig - already exists: " << +cig_id; 186 187 btsnd_hcic_set_cig_params( 188 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 189 cig_params.sca, cig_params.packing, cig_params.framing, 190 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 191 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 192 base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this), 193 cig_id, cig_params.sdu_itv_mtos)); 194 195 BTM_LogHistory( 196 kBtmLogTag, RawAddress::kEmpty, "CIG Create", 197 base::StringPrintf("cig_id:0x%02x, size: %d", cig_id, 198 static_cast<int>(cig_params.cis_cfgs.size()))); 199 } 200 reconfigure_cigiso_impl201 void reconfigure_cig(uint8_t cig_id, 202 struct iso_manager::cig_create_params cig_params) { 203 LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id; 204 205 btsnd_hcic_set_cig_params( 206 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 207 cig_params.sca, cig_params.packing, cig_params.framing, 208 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 209 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 210 base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this), 211 cig_id, cig_params.sdu_itv_mtos)); 212 } 213 on_remove_cigiso_impl214 void on_remove_cig(uint8_t* stream, uint16_t len) { 215 cig_remove_cmpl_evt evt; 216 217 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 218 LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; 219 220 STREAM_TO_UINT8(evt.status, stream); 221 STREAM_TO_UINT8(evt.cig_id, stream); 222 223 BTM_LogHistory( 224 kBtmLogTag, RawAddress::kEmpty, "CIG Remove complete", 225 base::StringPrintf( 226 "cig_id:0x%02x, status: %s", evt.cig_id, 227 hci_status_code_text((tHCI_STATUS)(evt.status)).c_str())); 228 229 if (evt.status == HCI_SUCCESS) { 230 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 231 while (cis_it != conn_hdl_to_cis_map_.cend()) { 232 if (cis_it->second->cig_id == evt.cig_id) 233 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 234 else 235 ++cis_it; 236 } 237 } 238 239 cig_callbacks_->OnCigEvent(kIsoEventCigOnRemoveCmpl, &evt); 240 241 { 242 const std::lock_guard<std::mutex> lock( 243 on_iso_traffic_active_callbacks_list_mutex_); 244 for (auto callback : on_iso_traffic_active_callbacks_list_) { 245 callback(false); 246 } 247 } 248 } 249 remove_cigiso_impl250 void remove_cig(uint8_t cig_id, bool force) { 251 if (!force) { 252 LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id; 253 } else { 254 LOG_WARN("Forcing to remove CIG %d", cig_id); 255 } 256 257 btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig, 258 base::Unretained(this))); 259 BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "CIG Remove", 260 base::StringPrintf("cig_id:0x%02x (f:%d)", cig_id, force)); 261 } 262 on_status_establish_cisiso_impl263 void on_status_establish_cis( 264 struct iso_manager::cis_establish_params conn_params, uint8_t* stream, 265 uint16_t len) { 266 uint8_t status; 267 268 LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; 269 270 STREAM_TO_UINT16(status, stream); 271 272 for (auto cis_param : conn_params.conn_pairs) { 273 cis_establish_cmpl_evt evt; 274 275 if (status != HCI_SUCCESS) { 276 auto cis = GetCisIfKnown(cis_param.cis_conn_handle); 277 LOG_ASSERT(cis != nullptr) 278 << "No such cis: " << +cis_param.cis_conn_handle; 279 280 evt.status = status; 281 evt.cis_conn_hdl = cis_param.cis_conn_handle; 282 evt.cig_id = 0xFF; 283 cis->state_flags &= ~kStateFlagIsConnecting; 284 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 285 286 BTM_LogHistory( 287 kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl], 288 "Establish CIS failed ", 289 base::StringPrintf( 290 "handle:0x%04x, status: %s", evt.cis_conn_hdl, 291 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 292 cis_hdl_to_addr.erase(evt.cis_conn_hdl); 293 } 294 } 295 } 296 establish_cisiso_impl297 void establish_cis(struct iso_manager::cis_establish_params conn_params) { 298 for (auto& el : conn_params.conn_pairs) { 299 auto cis = GetCisIfKnown(el.cis_conn_handle); 300 LOG_ASSERT(cis) << "No such cis: " << +el.cis_conn_handle; 301 LOG_ASSERT(!(cis->state_flags & 302 (kStateFlagIsConnected | kStateFlagIsConnecting))) 303 << "Already connected or connecting"; 304 cis->state_flags |= kStateFlagIsConnecting; 305 306 tBTM_SEC_DEV_REC* p_rec = btm_find_dev_by_handle(el.acl_conn_handle); 307 if (p_rec) { 308 cis_hdl_to_addr[el.cis_conn_handle] = p_rec->ble.pseudo_addr; 309 BTM_LogHistory(kBtmLogTag, p_rec->ble.pseudo_addr, "Establish CIS", 310 base::StringPrintf("handle:0x%04x", el.acl_conn_handle)); 311 } 312 } 313 btsnd_hcic_create_cis(conn_params.conn_pairs.size(), 314 conn_params.conn_pairs.data(), 315 base::BindOnce(&iso_impl::on_status_establish_cis, 316 base::Unretained(this), conn_params)); 317 } 318 disconnect_cisiso_impl319 void disconnect_cis(uint16_t cis_handle, uint8_t reason) { 320 auto cis = GetCisIfKnown(cis_handle); 321 LOG_ASSERT(cis) << "No such cis: " << +cis_handle; 322 LOG_ASSERT(cis->state_flags & kStateFlagIsConnected || 323 cis->state_flags & kStateFlagIsConnecting) 324 << "Not connected"; 325 bluetooth::legacy::hci::GetInterface().Disconnect( 326 cis_handle, static_cast<tHCI_STATUS>(reason)); 327 328 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[cis_handle], "Disconnect CIS ", 329 base::StringPrintf( 330 "handle:0x%04x, reason:%s", cis_handle, 331 hci_reason_code_text((tHCI_REASON)(reason)).c_str())); 332 } 333 on_setup_iso_data_pathiso_impl334 void on_setup_iso_data_path(uint8_t* stream, uint16_t len) { 335 uint8_t status; 336 uint16_t conn_handle; 337 338 STREAM_TO_UINT8(status, stream); 339 STREAM_TO_UINT16(conn_handle, stream); 340 341 iso_base* iso = GetIsoIfKnown(conn_handle); 342 if (iso == nullptr) { 343 /* That can happen when ACL has been disconnected while ISO patch was 344 * creating */ 345 LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle; 346 return; 347 } 348 349 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle], 350 "Setup data path complete", 351 base::StringPrintf( 352 "handle:0x%04x, status:%s", conn_handle, 353 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 354 355 if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet; 356 if (iso->state_flags & kStateFlagIsBroadcast) { 357 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 358 big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle); 359 } else { 360 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 361 cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id); 362 } 363 } 364 setup_iso_data_pathiso_impl365 void setup_iso_data_path( 366 uint16_t conn_handle, 367 struct iso_manager::iso_data_path_params path_params) { 368 iso_base* iso = GetIsoIfKnown(conn_handle); 369 LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle; 370 371 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 372 LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) 373 << "CIS not established"; 374 } 375 376 btsnd_hcic_setup_iso_data_path( 377 conn_handle, path_params.data_path_dir, path_params.data_path_id, 378 path_params.codec_id_format, path_params.codec_id_company, 379 path_params.codec_id_vendor, path_params.controller_delay, 380 std::move(path_params.codec_conf), 381 base::BindOnce(&iso_impl::on_setup_iso_data_path, 382 base::Unretained(this))); 383 BTM_LogHistory( 384 kBtmLogTag, cis_hdl_to_addr[conn_handle], "Setup data path", 385 base::StringPrintf( 386 "handle:0x%04x, dir:0x%02x, path_id:0x%02x, codec_id:0x%02x", 387 conn_handle, path_params.data_path_dir, path_params.data_path_id, 388 path_params.codec_id_format)); 389 } 390 on_remove_iso_data_pathiso_impl391 void on_remove_iso_data_path(uint8_t* stream, uint16_t len) { 392 uint8_t status; 393 uint16_t conn_handle; 394 395 if (len < 3) { 396 LOG(WARNING) << __func__ << "Malformatted packet received"; 397 return; 398 } 399 STREAM_TO_UINT8(status, stream); 400 STREAM_TO_UINT16(conn_handle, stream); 401 402 iso_base* iso = GetIsoIfKnown(conn_handle); 403 if (iso == nullptr) { 404 /* That could happen when ACL has been disconnected while removing data 405 * path */ 406 LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle; 407 return; 408 } 409 410 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle], 411 "Remove data path complete", 412 base::StringPrintf( 413 "handle:0x%04x, status:%s", conn_handle, 414 hci_status_code_text((tHCI_STATUS)(status)).c_str())); 415 416 if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet; 417 418 if (iso->state_flags & kStateFlagIsBroadcast) { 419 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 420 big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle); 421 } else { 422 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 423 cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id); 424 } 425 } 426 remove_iso_data_pathiso_impl427 void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { 428 iso_base* iso = GetIsoIfKnown(iso_handle); 429 LOG_ASSERT(iso != nullptr) << "No such iso connection: " << loghex(iso_handle); 430 LOG_ASSERT((iso->state_flags & kStateFlagHasDataPathSet) == 431 kStateFlagHasDataPathSet) 432 << "Data path not set"; 433 434 btsnd_hcic_remove_iso_data_path( 435 iso_handle, data_path_dir, 436 base::BindOnce(&iso_impl::on_remove_iso_data_path, 437 base::Unretained(this))); 438 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[iso_handle], "Remove data path", 439 base::StringPrintf("handle:0x%04x, dir:0x%02x", iso_handle, 440 data_path_dir)); 441 } 442 on_iso_link_quality_readiso_impl443 void on_iso_link_quality_read(uint8_t* stream, uint16_t len) { 444 uint8_t status; 445 uint16_t conn_handle; 446 uint32_t txUnackedPackets; 447 uint32_t txFlushedPackets; 448 uint32_t txLastSubeventPackets; 449 uint32_t retransmittedPackets; 450 uint32_t crcErrorPackets; 451 uint32_t rxUnreceivedPackets; 452 uint32_t duplicatePackets; 453 454 // 1 + 2 + 4 * 7 455 #define ISO_LINK_QUALITY_SIZE 31 456 if (len < ISO_LINK_QUALITY_SIZE) { 457 LOG(ERROR) << "Malformated link quality format, len=" << len; 458 return; 459 } 460 461 STREAM_TO_UINT8(status, stream); 462 if (status != HCI_SUCCESS) { 463 LOG(ERROR) << "Failed to Read ISO Link Quality, status: " 464 << loghex(status); 465 return; 466 } 467 468 STREAM_TO_UINT16(conn_handle, stream); 469 470 iso_base* iso = GetIsoIfKnown(conn_handle); 471 if (iso == nullptr) { 472 /* That could happen when ACL has been disconnected while waiting on the 473 * read respose */ 474 LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle; 475 return; 476 } 477 478 STREAM_TO_UINT32(txUnackedPackets, stream); 479 STREAM_TO_UINT32(txFlushedPackets, stream); 480 STREAM_TO_UINT32(txLastSubeventPackets, stream); 481 STREAM_TO_UINT32(retransmittedPackets, stream); 482 STREAM_TO_UINT32(crcErrorPackets, stream); 483 STREAM_TO_UINT32(rxUnreceivedPackets, stream); 484 STREAM_TO_UINT32(duplicatePackets, stream); 485 486 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 487 cig_callbacks_->OnIsoLinkQualityRead( 488 conn_handle, iso->cig_id, txUnackedPackets, txFlushedPackets, 489 txLastSubeventPackets, retransmittedPackets, crcErrorPackets, 490 rxUnreceivedPackets, duplicatePackets); 491 } 492 read_iso_link_qualityiso_impl493 void read_iso_link_quality(uint16_t iso_handle) { 494 iso_base* iso = GetIsoIfKnown(iso_handle); 495 if (iso == nullptr) { 496 LOG(ERROR) << __func__ << "No such iso connection: " << loghex(iso_handle); 497 return; 498 } 499 500 btsnd_hcic_read_iso_link_quality( 501 iso_handle, base::BindOnce(&iso_impl::on_iso_link_quality_read, 502 base::Unretained(this))); 503 } 504 prepare_ts_hci_packetiso_impl505 BT_HDR* prepare_ts_hci_packet(uint16_t iso_handle, uint32_t ts, 506 uint16_t seq_nb, uint16_t data_len) { 507 /* Add 2 for packet seq., 2 for length, 4 for the timestamp */ 508 uint16_t iso_data_load_len = data_len + 8; 509 510 /* Add 2 for handle, 2 for length */ 511 uint16_t iso_full_len = iso_data_load_len + 4; 512 BT_HDR* packet = (BT_HDR*)osi_malloc(iso_full_len + sizeof(BT_HDR)); 513 packet->len = iso_full_len; 514 packet->offset = 0; 515 packet->event = MSG_STACK_TO_HC_HCI_ISO; 516 packet->layer_specific = 0; 517 518 uint8_t* packet_data = packet->data; 519 UINT16_TO_STREAM(packet_data, iso_handle); 520 UINT16_TO_STREAM(packet_data, iso_data_load_len); 521 522 packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS; 523 UINT32_TO_STREAM(packet_data, ts); 524 525 UINT16_TO_STREAM(packet_data, seq_nb); 526 UINT16_TO_STREAM(packet_data, data_len); 527 528 return packet; 529 } 530 send_iso_data_hci_packetiso_impl531 void send_iso_data_hci_packet(BT_HDR* packet) { 532 bte_main_hci_send(packet, MSG_STACK_TO_HC_HCI_ISO | 0x0001); 533 } 534 send_iso_dataiso_impl535 void send_iso_data(uint16_t iso_handle, const uint8_t* data, 536 uint16_t data_len) { 537 iso_base* iso = GetIsoIfKnown(iso_handle); 538 LOG_ASSERT(iso != nullptr) 539 << "No such iso connection handle: " << loghex(iso_handle); 540 541 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 542 if (!(iso->state_flags & kStateFlagIsConnected)) { 543 LOG(WARNING) << __func__ << "Cis handle: " << loghex(iso_handle) 544 << " not established"; 545 return; 546 } 547 } 548 549 if (!(iso->state_flags & kStateFlagHasDataPathSet)) { 550 LOG_WARN("Data path not set for handle: 0x%04x", iso_handle); 551 return; 552 } 553 554 /* Calculate sequence number for the ISO data packet. 555 * It should be incremented by 1 every SDU Interval. 556 */ 557 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 558 iso->sync_info.seq_nb = (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv; 559 560 if (iso_credits_ == 0 || data_len > iso_buffer_size_) { 561 iso->cr_stats.credits_underflow_bytes += data_len; 562 iso->cr_stats.credits_underflow_count++; 563 iso->cr_stats.credits_last_underflow_us = 564 bluetooth::common::time_get_os_boottime_us(); 565 566 LOG(WARNING) << __func__ << ", dropping ISO packet, len: " 567 << static_cast<int>(data_len) 568 << ", iso credits: " << static_cast<int>(iso_credits_) 569 << ", iso handle: " << loghex(iso_handle); 570 return; 571 } 572 573 iso_credits_--; 574 iso->used_credits++; 575 576 BT_HDR* packet = 577 prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len); 578 memcpy(packet->data + kIsoDataInTsBtHdrOffset, data, data_len); 579 send_iso_data_hci_packet(packet); 580 } 581 process_cis_est_pktiso_impl582 void process_cis_est_pkt(uint8_t len, uint8_t* data) { 583 cis_establish_cmpl_evt evt; 584 585 LOG_ASSERT(len == 28) << "Invalid packet length: " << +len; 586 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 587 588 STREAM_TO_UINT8(evt.status, data); 589 STREAM_TO_UINT16(evt.cis_conn_hdl, data); 590 591 auto cis = GetCisIfKnown(evt.cis_conn_hdl); 592 LOG_ASSERT(cis != nullptr) << "No such cis: " << +evt.cis_conn_hdl; 593 594 BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl], 595 "CIS established event", 596 base::StringPrintf( 597 "cis_handle:0x%04x status:%s", evt.cis_conn_hdl, 598 hci_error_code_text((tHCI_STATUS)(evt.status)).c_str())); 599 600 cis->sync_info.first_sync_ts = bluetooth::common::time_get_os_boottime_us(); 601 602 STREAM_TO_UINT24(evt.cig_sync_delay, data); 603 STREAM_TO_UINT24(evt.cis_sync_delay, data); 604 STREAM_TO_UINT24(evt.trans_lat_mtos, data); 605 STREAM_TO_UINT24(evt.trans_lat_stom, data); 606 STREAM_TO_UINT8(evt.phy_mtos, data); 607 STREAM_TO_UINT8(evt.phy_stom, data); 608 STREAM_TO_UINT8(evt.nse, data); 609 STREAM_TO_UINT8(evt.bn_mtos, data); 610 STREAM_TO_UINT8(evt.bn_stom, data); 611 STREAM_TO_UINT8(evt.ft_mtos, data); 612 STREAM_TO_UINT8(evt.ft_stom, data); 613 STREAM_TO_UINT16(evt.max_pdu_mtos, data); 614 STREAM_TO_UINT16(evt.max_pdu_stom, data); 615 STREAM_TO_UINT16(evt.iso_itv, data); 616 617 if (evt.status == HCI_SUCCESS) { 618 cis->state_flags |= kStateFlagIsConnected; 619 } else { 620 cis_hdl_to_addr.erase(evt.cis_conn_hdl); 621 } 622 623 cis->state_flags &= ~kStateFlagIsConnecting; 624 625 evt.cig_id = cis->cig_id; 626 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 627 } 628 disconnection_completeiso_impl629 void disconnection_complete(uint16_t handle, uint8_t reason) { 630 /* Check if this is an ISO handle */ 631 auto cis = GetCisIfKnown(handle); 632 if (cis == nullptr) return; 633 634 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 635 636 LOG_INFO("%s flags: %d", __func__, +cis->state_flags); 637 638 BTM_LogHistory( 639 kBtmLogTag, cis_hdl_to_addr[handle], "CIS disconnected", 640 base::StringPrintf("cis_handle:0x%04x, reason:%s", handle, 641 hci_error_code_text((tHCI_REASON)(reason)).c_str())); 642 cis_hdl_to_addr.erase(handle); 643 644 if (cis->state_flags & kStateFlagIsConnected) { 645 cis_disconnected_evt evt = { 646 .reason = reason, 647 .cis_conn_hdl = handle, 648 .cig_id = cis->cig_id, 649 }; 650 651 cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); 652 cis->state_flags &= ~kStateFlagIsConnected; 653 654 /* return used credits */ 655 iso_credits_ += cis->used_credits; 656 cis->used_credits = 0; 657 658 /* Data path is considered still valid, but can be reconfigured only once 659 * CIS is reestablished. 660 */ 661 } 662 } 663 handle_num_completed_pktsiso_impl664 void handle_num_completed_pkts(uint8_t* p, uint8_t evt_len) { 665 uint8_t num_handles; 666 667 STREAM_TO_UINT8(num_handles, p); 668 669 LOG_ASSERT(evt_len == num_handles * 4 + 1); 670 671 for (int i = 0; i < num_handles; i++) { 672 uint16_t handle, num_sent; 673 674 STREAM_TO_UINT16(handle, p); 675 STREAM_TO_UINT16(num_sent, p); 676 677 auto iter = conn_hdl_to_cis_map_.find(handle); 678 if (iter != conn_hdl_to_cis_map_.end()) { 679 iter->second->used_credits -= num_sent; 680 iso_credits_ += num_sent; 681 continue; 682 } 683 684 iter = conn_hdl_to_bis_map_.find(handle); 685 if (iter != conn_hdl_to_bis_map_.end()) { 686 iter->second->used_credits -= num_sent; 687 iso_credits_ += num_sent; 688 continue; 689 } 690 } 691 } 692 handle_gd_num_completed_pktsiso_impl693 void handle_gd_num_completed_pkts(uint16_t handle, uint16_t credits) { 694 auto iter = conn_hdl_to_cis_map_.find(handle); 695 if (iter != conn_hdl_to_cis_map_.end()) { 696 iter->second->used_credits -= credits; 697 iso_credits_ += credits; 698 return; 699 } 700 701 iter = conn_hdl_to_bis_map_.find(handle); 702 if (iter != conn_hdl_to_bis_map_.end()) { 703 iter->second->used_credits -= credits; 704 iso_credits_ += credits; 705 } 706 } 707 process_create_big_cmpl_pktiso_impl708 void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { 709 struct big_create_cmpl_evt evt; 710 711 LOG_ASSERT(len >= 18) << "Invalid packet length: " << +len; 712 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 713 714 STREAM_TO_UINT8(evt.status, data); 715 STREAM_TO_UINT8(evt.big_id, data); 716 STREAM_TO_UINT24(evt.big_sync_delay, data); 717 STREAM_TO_UINT24(evt.transport_latency_big, data); 718 STREAM_TO_UINT8(evt.phy, data); 719 STREAM_TO_UINT8(evt.nse, data); 720 STREAM_TO_UINT8(evt.bn, data); 721 STREAM_TO_UINT8(evt.pto, data); 722 STREAM_TO_UINT8(evt.irc, data); 723 STREAM_TO_UINT16(evt.max_pdu, data); 724 STREAM_TO_UINT16(evt.iso_interval, data); 725 726 uint8_t num_bis; 727 STREAM_TO_UINT8(num_bis, data); 728 729 LOG_ASSERT(num_bis != 0) << "Bis count is 0"; 730 LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t))) 731 << "Invalid packet length: " << len << ". Number of bis: " << +num_bis; 732 733 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 734 for (auto i = 0; i < num_bis; ++i) { 735 uint16_t conn_handle; 736 STREAM_TO_UINT16(conn_handle, data); 737 evt.conn_handles.push_back(conn_handle); 738 LOG_INFO(" received BIS conn_hdl %d", +conn_handle); 739 740 if (evt.status == HCI_SUCCESS) { 741 auto bis = std::unique_ptr<iso_bis>(new iso_bis()); 742 bis->big_handle = evt.big_id; 743 bis->sdu_itv = last_big_create_req_sdu_itv_; 744 bis->sync_info = {.first_sync_ts = ts, .seq_nb = 0}; 745 bis->used_credits = 0; 746 bis->state_flags = kStateFlagIsBroadcast; 747 conn_hdl_to_bis_map_[conn_handle] = std::move(bis); 748 } 749 } 750 751 big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt); 752 753 { 754 const std::lock_guard<std::mutex> lock( 755 on_iso_traffic_active_callbacks_list_mutex_); 756 for (auto callbacks : on_iso_traffic_active_callbacks_list_) { 757 callbacks(true); 758 } 759 } 760 } 761 process_terminate_big_cmpl_pktiso_impl762 void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { 763 struct big_terminate_cmpl_evt evt; 764 765 LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; 766 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 767 768 STREAM_TO_UINT8(evt.big_id, data); 769 STREAM_TO_UINT8(evt.reason, data); 770 771 bool is_known_handle = false; 772 auto bis_it = conn_hdl_to_bis_map_.cbegin(); 773 while (bis_it != conn_hdl_to_bis_map_.cend()) { 774 if (bis_it->second->big_handle == evt.big_id) { 775 bis_it = conn_hdl_to_bis_map_.erase(bis_it); 776 is_known_handle = true; 777 } else { 778 ++bis_it; 779 } 780 } 781 782 LOG_ASSERT(is_known_handle) << "No such big: " << +evt.big_id; 783 big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); 784 785 { 786 const std::lock_guard<std::mutex> lock( 787 on_iso_traffic_active_callbacks_list_mutex_); 788 for (auto callbacks : on_iso_traffic_active_callbacks_list_) { 789 callbacks(false); 790 } 791 } 792 } 793 create_bigiso_impl794 void create_big(uint8_t big_id, struct big_create_params big_params) { 795 LOG_ASSERT(!IsBigKnown(big_id)) 796 << "Invalid big - already exists: " << +big_id; 797 798 if (stack_config_get_interface()->get_pts_unencrypt_broadcast()) { 799 LOG_INFO("Force create broadcst without encryption for PTS test"); 800 big_params.enc = 0; 801 big_params.enc_code = {0}; 802 } 803 804 last_big_create_req_sdu_itv_ = big_params.sdu_itv; 805 btsnd_hcic_create_big( 806 big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv, 807 big_params.max_sdu_size, big_params.max_transport_latency, 808 big_params.rtn, big_params.phy, big_params.packing, big_params.framing, 809 big_params.enc, big_params.enc_code); 810 } 811 terminate_bigiso_impl812 void terminate_big(uint8_t big_id, uint8_t reason) { 813 LOG_ASSERT(IsBigKnown(big_id)) << "No such big: " << +big_id; 814 815 btsnd_hcic_term_big(big_id, reason); 816 } 817 on_iso_eventiso_impl818 void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) { 819 switch (code) { 820 case HCI_BLE_CIS_EST_EVT: 821 process_cis_est_pkt(packet_len, packet); 822 break; 823 case HCI_BLE_CREATE_BIG_CPL_EVT: 824 process_create_big_cmpl_pkt(packet_len, packet); 825 break; 826 case HCI_BLE_TERM_BIG_CPL_EVT: 827 process_terminate_big_cmpl_pkt(packet_len, packet); 828 break; 829 case HCI_BLE_CIS_REQ_EVT: 830 /* Not supported */ 831 break; 832 case HCI_BLE_BIG_SYNC_EST_EVT: 833 /* Not supported */ 834 break; 835 case HCI_BLE_BIG_SYNC_LOST_EVT: 836 /* Not supported */ 837 break; 838 default: 839 LOG_ERROR("Unhandled event code %d", +code); 840 } 841 } 842 handle_iso_dataiso_impl843 void handle_iso_data(BT_HDR* p_msg) { 844 const uint8_t* stream = p_msg->data; 845 cis_data_evt evt; 846 uint16_t handle, seq_nb; 847 848 if (p_msg->len <= ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) 849 ? kIsoHeaderWithTsLen 850 : kIsoHeaderWithoutTsLen)) 851 return; 852 853 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 854 855 STREAM_TO_UINT16(handle, stream); 856 evt.cis_conn_hdl = HCID_GET_HANDLE(handle); 857 858 iso_base* iso = GetCisIfKnown(evt.cis_conn_hdl); 859 if (iso == nullptr) { 860 LOG(ERROR) << __func__ << ", received data for the non-registered CIS!"; 861 return; 862 } 863 864 STREAM_SKIP_UINT16(stream); 865 if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) { 866 STREAM_TO_UINT32(evt.ts, stream); 867 } else { 868 evt.ts = 0; 869 } 870 871 STREAM_TO_UINT16(seq_nb, stream); 872 873 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 874 uint32_t new_calc_seq_nb = 875 (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv; 876 if (new_calc_seq_nb <= iso->sync_info.seq_nb) 877 new_calc_seq_nb = iso->sync_info.seq_nb + 1; 878 879 if (iso->sync_info.seq_nb == 0) { 880 evt.evt_lost = 0; 881 } else { 882 evt.evt_lost = new_calc_seq_nb - iso->sync_info.seq_nb - 1; 883 if (evt.evt_lost > 0) { 884 iso->evt_stats.evt_lost_count += evt.evt_lost; 885 iso->evt_stats.evt_last_lost_us = 886 bluetooth::common::time_get_os_boottime_us(); 887 888 LOG(WARNING) << evt.evt_lost << " packets possibly lost."; 889 } 890 891 if (new_calc_seq_nb != seq_nb) { 892 LOG(WARNING) << "Sequence number mismatch. " 893 "Adjusting own time reference point."; 894 iso->sync_info.first_sync_ts = ts - (seq_nb * iso->sdu_itv); 895 new_calc_seq_nb = seq_nb; 896 897 iso->evt_stats.seq_nb_mismatch_count++; 898 } 899 } 900 iso->sync_info.seq_nb = new_calc_seq_nb; 901 902 evt.p_msg = p_msg; 903 evt.cig_id = iso->cig_id; 904 evt.seq_nb = seq_nb; 905 cig_callbacks_->OnCisEvent(kIsoEventCisDataAvailable, &evt); 906 } 907 GetCisIfKnowniso_impl908 iso_cis* GetCisIfKnown(uint16_t cis_conn_handle) { 909 auto cis_it = conn_hdl_to_cis_map_.find(cis_conn_handle); 910 return (cis_it != conn_hdl_to_cis_map_.end()) ? cis_it->second.get() 911 : nullptr; 912 } 913 GetBisIfKnowniso_impl914 iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) { 915 auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle); 916 return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get() 917 : nullptr; 918 } 919 GetIsoIfKnowniso_impl920 iso_base* GetIsoIfKnown(uint16_t iso_handle) { 921 struct iso_base* iso = GetCisIfKnown(iso_handle); 922 return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle); 923 } 924 IsCigKnowniso_impl925 bool IsCigKnown(uint8_t cig_id) const { 926 auto const cis_it = 927 std::find_if(conn_hdl_to_cis_map_.cbegin(), conn_hdl_to_cis_map_.cend(), 928 [&cig_id](auto& kv_pair) { 929 return (kv_pair.second->cig_id == cig_id); 930 }); 931 return (cis_it != conn_hdl_to_cis_map_.cend()); 932 } 933 IsBigKnowniso_impl934 bool IsBigKnown(uint8_t big_id) const { 935 auto bis_it = 936 std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(), 937 [&big_id](auto& kv_pair) { 938 return (kv_pair.second->big_handle == big_id); 939 }); 940 return (bis_it != conn_hdl_to_bis_map_.cend()); 941 } 942 dump_credits_statsiso_impl943 static void dump_credits_stats(int fd, const iso_base::credits_stats& stats) { 944 uint64_t now_us = bluetooth::common::time_get_os_boottime_us(); 945 946 dprintf(fd, " Credits Stats:\n"); 947 dprintf(fd, " Credits underflow (count): %zu\n", 948 stats.credits_underflow_count); 949 dprintf(fd, " Credits underflow (bytes): %zu\n", 950 stats.credits_underflow_bytes); 951 dprintf( 952 fd, " Last underflow time ago (ms): %llu\n", 953 (stats.credits_last_underflow_us > 0 954 ? (unsigned long long)(now_us - stats.credits_last_underflow_us) / 955 1000 956 : 0llu)); 957 } 958 dump_event_statsiso_impl959 static void dump_event_stats(int fd, const iso_base::event_stats& stats) { 960 uint64_t now_us = bluetooth::common::time_get_os_boottime_us(); 961 962 dprintf(fd, " Event Stats:\n"); 963 dprintf(fd, " Sequence number mismatch (count): %zu\n", 964 stats.seq_nb_mismatch_count); 965 dprintf(fd, " Event lost (count): %zu\n", stats.evt_lost_count); 966 dprintf(fd, " Last event lost time ago (ms): %llu\n", 967 (stats.evt_last_lost_us > 0 968 ? (unsigned long long)(now_us - stats.evt_last_lost_us) / 1000 969 : 0llu)); 970 } 971 dumpiso_impl972 void dump(int fd) const { 973 dprintf(fd, " ----------------\n "); 974 dprintf(fd, " ISO Manager:\n"); 975 dprintf(fd, " Available credits: %d\n", iso_credits_.load()); 976 dprintf(fd, " Controller buffer size: %d\n", iso_buffer_size_); 977 dprintf(fd, " Num of ISO traffic callbacks: %lu\n", 978 static_cast<unsigned long>( 979 on_iso_traffic_active_callbacks_list_.size())); 980 dprintf(fd, " CISes:\n"); 981 for (auto const& cis_pair : conn_hdl_to_cis_map_) { 982 dprintf(fd, " CIS Connection handle: %d\n", cis_pair.first); 983 dprintf(fd, " CIG ID: %d\n", cis_pair.second->cig_id); 984 dprintf(fd, " Used Credits: %d\n", 985 cis_pair.second->used_credits.load()); 986 dprintf(fd, " SDU Interval: %d\n", cis_pair.second->sdu_itv); 987 dprintf(fd, " State Flags: 0x%02hx\n", 988 cis_pair.second->state_flags.load()); 989 dump_credits_stats(fd, cis_pair.second->cr_stats); 990 dump_event_stats(fd, cis_pair.second->evt_stats); 991 } 992 dprintf(fd, " BISes:\n"); 993 for (auto const& cis_pair : conn_hdl_to_bis_map_) { 994 dprintf(fd, " BIS Connection handle: %d\n", cis_pair.first); 995 dprintf(fd, " BIG Handle: %d\n", cis_pair.second->big_handle); 996 dprintf(fd, " Used Credits: %d\n", 997 cis_pair.second->used_credits.load()); 998 dprintf(fd, " SDU Interval: %d\n", cis_pair.second->sdu_itv); 999 dprintf(fd, " State Flags: 0x%02hx\n", 1000 cis_pair.second->state_flags.load()); 1001 dump_credits_stats(fd, cis_pair.second->cr_stats); 1002 dump_event_stats(fd, cis_pair.second->evt_stats); 1003 } 1004 dprintf(fd, " ----------------\n "); 1005 } 1006 1007 std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_; 1008 std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_; 1009 std::map<uint16_t, RawAddress> cis_hdl_to_addr; 1010 1011 std::atomic_uint16_t iso_credits_; 1012 uint16_t iso_buffer_size_; 1013 uint32_t last_big_create_req_sdu_itv_; 1014 1015 CigCallbacks* cig_callbacks_ = nullptr; 1016 BigCallbacks* big_callbacks_ = nullptr; 1017 std::mutex on_iso_traffic_active_callbacks_list_mutex_; 1018 std::list<void (*)(bool)> on_iso_traffic_active_callbacks_list_; 1019 }; 1020 1021 } // namespace iso_manager 1022 } // namespace hci 1023 } // namespace bluetooth 1024