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