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/bind_helpers.h" 26 #include "base/callback.h" 27 #include "bt_types.h" 28 #include "btm_iso_api.h" 29 #include "btu.h" 30 #include "common/time_util.h" 31 #include "device/include/controller.h" 32 #include "osi/include/log.h" 33 34 namespace bluetooth { 35 namespace hci { 36 namespace iso_manager { 37 static constexpr uint8_t kIsoDataInTsBtHdrOffset = 0x0C; 38 static constexpr uint8_t kIsoHeaderWithTsLen = 12; 39 static constexpr uint8_t kIsoHeaderWithoutTsLen = 8; 40 41 static constexpr uint8_t kStateFlagsNone = 0x00; 42 static constexpr uint8_t kStateFlagIsConnected = 0x01; 43 static constexpr uint8_t kStateFlagHasDataPathSet = 0x02; 44 static constexpr uint8_t kStateFlagIsBroadcast = 0x04; 45 46 struct iso_sync_info { 47 uint32_t first_sync_ts; 48 uint16_t seq_nb; 49 }; 50 51 struct iso_base { 52 union { 53 uint8_t cig_id; 54 uint8_t big_handle; 55 }; 56 57 struct iso_sync_info sync_info; 58 uint8_t state_flags; 59 uint32_t sdu_itv; 60 }; 61 62 typedef iso_base iso_cis; 63 typedef iso_base iso_bis; 64 65 struct iso_impl { iso_impliso_impl66 iso_impl() { 67 iso_credits_ = controller_get_interface()->get_iso_buffer_count(); 68 iso_buffer_size_ = controller_get_interface()->get_iso_data_size(); 69 } 70 ~iso_impliso_impl71 ~iso_impl() {} 72 handle_register_cis_callbacksiso_impl73 void handle_register_cis_callbacks(CigCallbacks* callbacks) { 74 LOG_ASSERT(callbacks != nullptr) << "Invalid CIG callbacks"; 75 cig_callbacks_ = callbacks; 76 } 77 handle_register_big_callbacksiso_impl78 void handle_register_big_callbacks(BigCallbacks* callbacks) { 79 LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks"; 80 big_callbacks_ = callbacks; 81 } 82 on_set_cig_paramsiso_impl83 void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream, 84 uint16_t len) { 85 uint8_t cis_cnt; 86 uint16_t conn_handle; 87 cig_create_cmpl_evt evt; 88 89 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 90 LOG_ASSERT(len >= 3) << "Invalid packet length."; 91 92 STREAM_TO_UINT8(evt.status, stream); 93 STREAM_TO_UINT8(evt.cig_id, stream); 94 STREAM_TO_UINT8(cis_cnt, stream); 95 96 uint8_t evt_code = IsCigKnown(cig_id) ? kIsoEventCigOnReconfigureCmpl 97 : kIsoEventCigOnCreateCmpl; 98 99 if (evt.status == HCI_SUCCESS) { 100 LOG_ASSERT(len >= (3) + (cis_cnt * sizeof(uint16_t))) 101 << "Invalid CIS count."; 102 103 /* Remove entries for the reconfigured CIG */ 104 if (evt_code == kIsoEventCigOnReconfigureCmpl) { 105 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 106 while (cis_it != conn_hdl_to_cis_map_.cend()) { 107 if (cis_it->second->cig_id == evt.cig_id) 108 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 109 else 110 ++cis_it; 111 } 112 } 113 114 evt.conn_handles.reserve(cis_cnt); 115 for (int i = 0; i < cis_cnt; i++) { 116 STREAM_TO_UINT16(conn_handle, stream); 117 118 evt.conn_handles.push_back(conn_handle); 119 conn_hdl_to_cis_map_[conn_handle] = std::unique_ptr<iso_cis>( 120 new iso_cis({.sync_info = {.first_sync_ts = 0, .seq_nb = 0}, 121 .cig_id = cig_id, 122 .state_flags = kStateFlagsNone, 123 .sdu_itv = sdu_itv_mtos})); 124 } 125 } 126 127 cig_callbacks_->OnCigEvent(evt_code, &evt); 128 } 129 create_cigiso_impl130 void create_cig(uint8_t cig_id, 131 struct iso_manager::cig_create_params cig_params) { 132 LOG_ASSERT(!IsCigKnown(cig_id)) << "Invalid cig - already exists."; 133 134 btsnd_hcic_set_cig_params( 135 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 136 cig_params.sca, cig_params.packing, cig_params.framing, 137 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 138 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 139 base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this), 140 cig_id, cig_params.sdu_itv_mtos)); 141 } 142 reconfigure_cigiso_impl143 void reconfigure_cig(uint8_t cig_id, 144 struct iso_manager::cig_create_params cig_params) { 145 LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig"; 146 147 btsnd_hcic_set_cig_params( 148 cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, 149 cig_params.sca, cig_params.packing, cig_params.framing, 150 cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos, 151 cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(), 152 base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this), 153 cig_id, cig_params.sdu_itv_mtos)); 154 } 155 on_remove_cigiso_impl156 void on_remove_cig(uint8_t* stream, uint16_t len) { 157 cig_remove_cmpl_evt evt; 158 159 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 160 LOG_ASSERT(len == 2) << "Invalid packet length."; 161 162 STREAM_TO_UINT8(evt.status, stream); 163 STREAM_TO_UINT8(evt.cig_id, stream); 164 165 if (evt.status == HCI_SUCCESS) { 166 auto cis_it = conn_hdl_to_cis_map_.cbegin(); 167 while (cis_it != conn_hdl_to_cis_map_.cend()) { 168 if (cis_it->second->cig_id == evt.cig_id) 169 cis_it = conn_hdl_to_cis_map_.erase(cis_it); 170 else 171 ++cis_it; 172 } 173 } 174 175 cig_callbacks_->OnCigEvent(kIsoEventCigOnRemoveCmpl, &evt); 176 } 177 remove_cigiso_impl178 void remove_cig(uint8_t cig_id) { 179 LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig"; 180 181 btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig, 182 base::Unretained(this))); 183 } 184 on_status_establish_cisiso_impl185 void on_status_establish_cis( 186 struct iso_manager::cis_establish_params conn_params, uint8_t* stream, 187 uint16_t len) { 188 uint8_t status; 189 190 LOG_ASSERT(len == 2) << "Invalid packet length: " << len; 191 192 STREAM_TO_UINT16(status, stream); 193 if (status == HCI_SUCCESS) { 194 /* Wait for connection established event */ 195 return; 196 } 197 198 for (auto cis : conn_params.conn_pairs) { 199 cis_establish_cmpl_evt evt; 200 201 evt.status = status; 202 evt.cis_conn_hdl = cis.cis_conn_handle; 203 evt.cig_id = 0xFF; 204 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 205 } 206 } 207 establish_cisiso_impl208 void establish_cis(struct iso_manager::cis_establish_params conn_params) { 209 for (auto& el : conn_params.conn_pairs) { 210 auto cis = GetCisIfKnown(el.cis_conn_handle); 211 LOG_ASSERT(cis) << "No such cis"; 212 LOG_ASSERT(!(cis->state_flags & kStateFlagIsConnected)) 213 << "Already connected"; 214 } 215 btsnd_hcic_create_cis(conn_params.conn_pairs.size(), 216 conn_params.conn_pairs.data(), 217 base::BindOnce(&iso_impl::on_status_establish_cis, 218 base::Unretained(this), conn_params)); 219 } 220 disconnect_cisiso_impl221 void disconnect_cis(uint16_t cis_handle, uint8_t reason) { 222 auto cis = GetCisIfKnown(cis_handle); 223 LOG_ASSERT(cis) << "No such cis"; 224 LOG_ASSERT(cis->state_flags & kStateFlagIsConnected) << "Not connected"; 225 bluetooth::legacy::hci::GetInterface().Disconnect( 226 cis_handle, static_cast<tHCI_STATUS>(reason)); 227 } 228 on_setup_iso_data_pathiso_impl229 void on_setup_iso_data_path(uint8_t* stream, uint16_t len) { 230 uint8_t status; 231 uint16_t conn_handle; 232 233 STREAM_TO_UINT8(status, stream); 234 STREAM_TO_UINT16(conn_handle, stream); 235 236 iso_base* iso = GetIsoIfKnown(conn_handle); 237 LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle; 238 239 if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet; 240 if (iso->state_flags & kStateFlagIsBroadcast) { 241 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 242 big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle); 243 } else { 244 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 245 cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id); 246 } 247 } 248 setup_iso_data_pathiso_impl249 void setup_iso_data_path( 250 uint16_t conn_handle, 251 struct iso_manager::iso_data_path_params path_params) { 252 iso_base* iso = GetIsoIfKnown(conn_handle); 253 LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle; 254 255 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 256 LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) 257 << "CIS not established"; 258 } 259 260 btsnd_hcic_setup_iso_data_path( 261 conn_handle, path_params.data_path_dir, path_params.data_path_id, 262 path_params.codec_id_format, path_params.codec_id_company, 263 path_params.codec_id_vendor, path_params.controller_delay, 264 std::move(path_params.codec_conf), 265 base::BindOnce(&iso_impl::on_setup_iso_data_path, 266 base::Unretained(this))); 267 } 268 on_remove_iso_data_pathiso_impl269 void on_remove_iso_data_path(uint8_t* stream, uint16_t len) { 270 uint8_t status; 271 uint16_t conn_handle; 272 273 STREAM_TO_UINT8(status, stream); 274 STREAM_TO_UINT16(conn_handle, stream); 275 276 iso_base* iso = GetIsoIfKnown(conn_handle); 277 LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle; 278 279 if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet; 280 281 if (iso->state_flags & kStateFlagIsBroadcast) { 282 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 283 big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle); 284 } else { 285 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 286 cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id); 287 } 288 } 289 remove_iso_data_pathiso_impl290 void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { 291 iso_base* iso = GetIsoIfKnown(iso_handle); 292 LOG_ASSERT(iso != nullptr) << "No such iso connection"; 293 LOG_ASSERT((iso->state_flags & kStateFlagHasDataPathSet) == 294 kStateFlagHasDataPathSet) 295 << "Data path not set"; 296 297 btsnd_hcic_remove_iso_data_path( 298 iso_handle, data_path_dir, 299 base::BindOnce(&iso_impl::on_remove_iso_data_path, 300 base::Unretained(this))); 301 } 302 on_iso_link_quality_readiso_impl303 void on_iso_link_quality_read(uint8_t* stream, uint16_t len) { 304 uint8_t status; 305 uint16_t conn_handle; 306 uint32_t txUnackedPackets; 307 uint32_t txFlushedPackets; 308 uint32_t txLastSubeventPackets; 309 uint32_t retransmittedPackets; 310 uint32_t crcErrorPackets; 311 uint32_t rxUnreceivedPackets; 312 uint32_t duplicatePackets; 313 314 STREAM_TO_UINT8(status, stream); 315 if (status != HCI_SUCCESS) { 316 LOG(ERROR) << "Failed to Read ISO Link Quality, status: " 317 << loghex(status); 318 return; 319 } 320 321 STREAM_TO_UINT16(conn_handle, stream); 322 323 iso_base* iso = GetIsoIfKnown(conn_handle); 324 LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle; 325 326 STREAM_TO_UINT32(txUnackedPackets, stream); 327 STREAM_TO_UINT32(txFlushedPackets, stream); 328 STREAM_TO_UINT32(txLastSubeventPackets, stream); 329 STREAM_TO_UINT32(retransmittedPackets, stream); 330 STREAM_TO_UINT32(crcErrorPackets, stream); 331 STREAM_TO_UINT32(rxUnreceivedPackets, stream); 332 STREAM_TO_UINT32(duplicatePackets, stream); 333 334 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 335 cig_callbacks_->OnIsoLinkQualityRead( 336 conn_handle, iso->cig_id, txUnackedPackets, txFlushedPackets, 337 txLastSubeventPackets, retransmittedPackets, crcErrorPackets, 338 rxUnreceivedPackets, duplicatePackets); 339 } 340 read_iso_link_qualityiso_impl341 void read_iso_link_quality(uint16_t iso_handle) { 342 iso_base* iso = GetIsoIfKnown(iso_handle); 343 LOG_ASSERT(iso != nullptr) << "No such iso connection"; 344 345 btsnd_hcic_read_iso_link_quality( 346 iso_handle, base::BindOnce(&iso_impl::on_iso_link_quality_read, 347 base::Unretained(this))); 348 } 349 prepare_ts_hci_packetiso_impl350 BT_HDR* prepare_ts_hci_packet(uint16_t iso_handle, uint32_t ts, 351 uint16_t seq_nb, uint16_t data_len) { 352 /* Add 2 for packet seq., 2 for length, 4 for the timestamp */ 353 uint16_t iso_data_load_len = data_len + 8; 354 355 /* Add 2 for handle, 2 for length */ 356 uint16_t iso_full_len = iso_data_load_len + 4; 357 BT_HDR* packet = (BT_HDR*)osi_malloc(iso_full_len + sizeof(BT_HDR)); 358 packet->len = iso_full_len; 359 packet->offset = 0; 360 packet->event = MSG_STACK_TO_HC_HCI_ISO; 361 packet->layer_specific = 0; 362 363 uint8_t* packet_data = packet->data; 364 UINT16_TO_STREAM(packet_data, iso_handle); 365 UINT16_TO_STREAM(packet_data, iso_data_load_len); 366 367 packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS; 368 UINT32_TO_STREAM(packet_data, ts); 369 370 UINT16_TO_STREAM(packet_data, seq_nb); 371 UINT16_TO_STREAM(packet_data, data_len); 372 373 return packet; 374 } 375 send_iso_data_hci_packetiso_impl376 void send_iso_data_hci_packet(BT_HDR* packet) { 377 bte_main_hci_send(packet, MSG_STACK_TO_HC_HCI_ISO | 0x0001); 378 } 379 send_iso_dataiso_impl380 void send_iso_data(uint16_t iso_handle, const uint8_t* data, 381 uint16_t data_len) { 382 iso_base* iso = GetIsoIfKnown(iso_handle); 383 LOG_ASSERT(iso != nullptr) 384 << "No such iso connection handle: " << +iso_handle; 385 386 if (!(iso->state_flags & kStateFlagIsBroadcast)) { 387 LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) 388 << "CIS not established"; 389 } 390 LOG_ASSERT(iso->state_flags & kStateFlagHasDataPathSet) 391 << "Data path not set for handle: " << +iso_handle; 392 393 /* Calculate sequence number for the ISO data packet. 394 * It should be incremented by 1 every SDU Interval. 395 */ 396 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 397 iso->sync_info.seq_nb = (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv; 398 399 if (iso_credits_ == 0 || data_len > iso_buffer_size_) { 400 LOG(WARNING) << __func__ << ", dropping ISO packet, len: " 401 << static_cast<int>(data_len) 402 << ", iso credits: " << static_cast<int>(iso_credits_); 403 return; 404 } 405 406 iso_credits_--; 407 408 BT_HDR* packet = 409 prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len); 410 memcpy(packet->data + kIsoDataInTsBtHdrOffset, data, data_len); 411 send_iso_data_hci_packet(packet); 412 } 413 process_cis_est_pktiso_impl414 void process_cis_est_pkt(uint8_t len, uint8_t* data) { 415 cis_establish_cmpl_evt evt; 416 417 LOG_ASSERT(len == 28) << "Invalid packet length"; 418 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 419 420 STREAM_TO_UINT8(evt.status, data); 421 STREAM_TO_UINT16(evt.cis_conn_hdl, data); 422 423 auto cis = GetCisIfKnown(evt.cis_conn_hdl); 424 LOG_ASSERT(cis != nullptr) << "No such cis"; 425 426 cis->sync_info.first_sync_ts = bluetooth::common::time_get_os_boottime_us(); 427 428 STREAM_TO_UINT24(evt.cig_sync_delay, data); 429 STREAM_TO_UINT24(evt.cis_sync_delay, data); 430 STREAM_TO_UINT24(evt.trans_lat_mtos, data); 431 STREAM_TO_UINT24(evt.trans_lat_stom, data); 432 STREAM_TO_UINT8(evt.phy_mtos, data); 433 STREAM_TO_UINT8(evt.phy_stom, data); 434 STREAM_TO_UINT8(evt.nse, data); 435 STREAM_TO_UINT8(evt.bn_mtos, data); 436 STREAM_TO_UINT8(evt.bn_stom, data); 437 STREAM_TO_UINT8(evt.ft_mtos, data); 438 STREAM_TO_UINT8(evt.ft_stom, data); 439 STREAM_TO_UINT16(evt.max_pdu_mtos, data); 440 STREAM_TO_UINT16(evt.max_pdu_stom, data); 441 STREAM_TO_UINT16(evt.iso_itv, data); 442 443 if (evt.status == HCI_SUCCESS) cis->state_flags |= kStateFlagIsConnected; 444 445 evt.cig_id = cis->cig_id; 446 cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt); 447 } 448 disconnection_completeiso_impl449 void disconnection_complete(uint16_t handle, uint8_t reason) { 450 /* Check if this is an ISO handle */ 451 auto cis = GetCisIfKnown(handle); 452 if (cis == nullptr) return; 453 454 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 455 456 LOG_INFO("%s flags: %d", __func__, +cis->state_flags); 457 if (cis->state_flags & kStateFlagIsConnected) { 458 cis_disconnected_evt evt = { 459 .reason = reason, 460 .cis_conn_hdl = handle, 461 .cig_id = cis->cig_id, 462 }; 463 464 cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); 465 cis->state_flags &= ~kStateFlagIsConnected; 466 /* Data path is considered still valid, but can be reconfigured only once 467 * CIS is reestablished. 468 */ 469 } 470 } 471 handle_num_completed_pktsiso_impl472 void handle_num_completed_pkts(uint8_t* p, uint8_t evt_len) { 473 uint8_t num_handles; 474 475 STREAM_TO_UINT8(num_handles, p); 476 477 LOG_ASSERT(evt_len == num_handles * 4 + 1); 478 479 for (int i = 0; i < num_handles; i++) { 480 uint16_t handle, num_sent; 481 482 STREAM_TO_UINT16(handle, p); 483 STREAM_TO_UINT16(num_sent, p); 484 485 if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && 486 (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) 487 continue; 488 489 iso_credits_ += num_sent; 490 } 491 } 492 process_create_big_cmpl_pktiso_impl493 void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { 494 struct big_create_cmpl_evt evt; 495 496 LOG_ASSERT(len >= 18) << "Invalid packet length"; 497 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 498 499 STREAM_TO_UINT8(evt.status, data); 500 STREAM_TO_UINT8(evt.big_id, data); 501 STREAM_TO_UINT24(evt.big_sync_delay, data); 502 STREAM_TO_UINT24(evt.transport_latency_big, data); 503 STREAM_TO_UINT8(evt.phy, data); 504 STREAM_TO_UINT8(evt.nse, data); 505 STREAM_TO_UINT8(evt.bn, data); 506 STREAM_TO_UINT8(evt.pto, data); 507 STREAM_TO_UINT8(evt.irc, data); 508 STREAM_TO_UINT16(evt.max_pdu, data); 509 STREAM_TO_UINT16(evt.iso_interval, data); 510 511 uint8_t num_bis; 512 STREAM_TO_UINT8(num_bis, data); 513 514 LOG_ASSERT(num_bis != 0) << "Invalid bis count"; 515 LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t))) 516 << "Invalid packet length"; 517 518 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 519 for (auto i = 0; i < num_bis; ++i) { 520 uint16_t conn_handle; 521 STREAM_TO_UINT16(conn_handle, data); 522 evt.conn_handles.push_back(conn_handle); 523 LOG_INFO(" received BIS conn_hdl %d", +conn_handle); 524 525 if (evt.status == HCI_SUCCESS) { 526 conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>( 527 new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0}, 528 .big_handle = evt.big_id, 529 .state_flags = kStateFlagIsBroadcast, 530 .sdu_itv = last_big_create_req_sdu_itv_})); 531 } 532 } 533 534 big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt); 535 } 536 process_terminate_big_cmpl_pktiso_impl537 void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { 538 struct big_terminate_cmpl_evt evt; 539 540 LOG_ASSERT(len == 2) << "Invalid packet length"; 541 LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; 542 543 STREAM_TO_UINT8(evt.big_id, data); 544 STREAM_TO_UINT8(evt.reason, data); 545 546 bool is_known_handle = false; 547 auto bis_it = conn_hdl_to_bis_map_.cbegin(); 548 while (bis_it != conn_hdl_to_bis_map_.cend()) { 549 if (bis_it->second->big_handle == evt.big_id) { 550 bis_it = conn_hdl_to_bis_map_.erase(bis_it); 551 is_known_handle = true; 552 } else { 553 ++bis_it; 554 } 555 } 556 557 LOG_ASSERT(is_known_handle) << "No such big"; 558 big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); 559 } 560 create_bigiso_impl561 void create_big(uint8_t big_id, struct big_create_params big_params) { 562 LOG_ASSERT(!IsBigKnown(big_id)) << "Invalid big - already exists"; 563 564 last_big_create_req_sdu_itv_ = big_params.sdu_itv; 565 btsnd_hcic_create_big( 566 big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv, 567 big_params.max_sdu_size, big_params.max_transport_latency, 568 big_params.rtn, big_params.phy, big_params.packing, big_params.framing, 569 big_params.enc, big_params.enc_code); 570 } 571 terminate_bigiso_impl572 void terminate_big(uint8_t big_id, uint8_t reason) { 573 LOG_ASSERT(IsBigKnown(big_id)) << "No such big"; 574 575 btsnd_hcic_term_big(big_id, reason); 576 } 577 on_iso_eventiso_impl578 void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) { 579 switch (code) { 580 case HCI_BLE_CIS_EST_EVT: 581 process_cis_est_pkt(packet_len, packet); 582 break; 583 case HCI_BLE_CREATE_BIG_CPL_EVT: 584 process_create_big_cmpl_pkt(packet_len, packet); 585 break; 586 case HCI_BLE_TERM_BIG_CPL_EVT: 587 process_terminate_big_cmpl_pkt(packet_len, packet); 588 break; 589 case HCI_BLE_CIS_REQ_EVT: 590 /* Not supported */ 591 break; 592 case HCI_BLE_BIG_SYNC_EST_EVT: 593 /* Not supported */ 594 break; 595 case HCI_BLE_BIG_SYNC_LOST_EVT: 596 /* Not supported */ 597 break; 598 default: 599 LOG_ERROR("Unhandled event code %d", +code); 600 } 601 } 602 handle_iso_dataiso_impl603 void handle_iso_data(BT_HDR* p_msg) { 604 const uint8_t* stream = p_msg->data; 605 cis_data_evt evt; 606 uint16_t handle, seq_nb; 607 608 if (p_msg->len <= ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) 609 ? kIsoHeaderWithTsLen 610 : kIsoHeaderWithoutTsLen)) 611 return; 612 613 LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; 614 615 STREAM_TO_UINT16(handle, stream); 616 evt.cis_conn_hdl = HCID_GET_HANDLE(handle); 617 618 iso_base* iso = GetCisIfKnown(evt.cis_conn_hdl); 619 if (iso == nullptr) { 620 LOG(ERROR) << __func__ << ", received data for the non-registered CIS!"; 621 return; 622 } 623 624 STREAM_SKIP_UINT16(stream); 625 if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) 626 STREAM_TO_UINT32(evt.ts, stream); 627 628 STREAM_TO_UINT16(seq_nb, stream); 629 630 uint32_t ts = bluetooth::common::time_get_os_boottime_us(); 631 uint32_t new_calc_seq_nb = 632 (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv; 633 if (new_calc_seq_nb <= iso->sync_info.seq_nb) 634 new_calc_seq_nb = iso->sync_info.seq_nb + 1; 635 636 if (iso->sync_info.seq_nb == 0) { 637 evt.evt_lost = 0; 638 } else { 639 evt.evt_lost = new_calc_seq_nb - iso->sync_info.seq_nb - 1; 640 if (evt.evt_lost > 0) { 641 LOG(WARNING) << evt.evt_lost << " packets possibly lost."; 642 } 643 644 if (new_calc_seq_nb != seq_nb) { 645 LOG(WARNING) << "Sequence number mismatch. " 646 "Adjusting own time reference point."; 647 iso->sync_info.first_sync_ts = ts - (seq_nb * iso->sdu_itv); 648 new_calc_seq_nb = seq_nb; 649 } 650 } 651 iso->sync_info.seq_nb = new_calc_seq_nb; 652 653 evt.p_msg = p_msg; 654 evt.cig_id = iso->cig_id; 655 cig_callbacks_->OnCisEvent(kIsoEventCisDataAvailable, &evt); 656 } 657 GetCisIfKnowniso_impl658 iso_cis* GetCisIfKnown(uint16_t cis_conn_handle) { 659 auto cis_it = conn_hdl_to_cis_map_.find(cis_conn_handle); 660 return (cis_it != conn_hdl_to_cis_map_.end()) ? cis_it->second.get() 661 : nullptr; 662 } 663 GetBisIfKnowniso_impl664 iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) { 665 auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle); 666 return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get() 667 : nullptr; 668 } 669 GetIsoIfKnowniso_impl670 iso_base* GetIsoIfKnown(uint16_t iso_handle) { 671 struct iso_base* iso = GetCisIfKnown(iso_handle); 672 return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle); 673 } 674 IsCigKnowniso_impl675 bool IsCigKnown(uint8_t cig_id) const { 676 auto const cis_it = 677 std::find_if(conn_hdl_to_cis_map_.cbegin(), conn_hdl_to_cis_map_.cend(), 678 [&cig_id](auto& kv_pair) { 679 return (kv_pair.second->cig_id == cig_id); 680 }); 681 return (cis_it != conn_hdl_to_cis_map_.cend()); 682 } 683 IsBigKnowniso_impl684 bool IsBigKnown(uint8_t big_id) const { 685 auto bis_it = 686 std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(), 687 [&big_id](auto& kv_pair) { 688 return (kv_pair.second->big_handle == big_id); 689 }); 690 return (bis_it != conn_hdl_to_bis_map_.cend()); 691 } 692 693 std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_; 694 std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_; 695 696 uint16_t iso_credits_; 697 uint16_t iso_buffer_size_; 698 uint32_t last_big_create_req_sdu_itv_; 699 700 CigCallbacks* cig_callbacks_ = nullptr; 701 BigCallbacks* big_callbacks_ = nullptr; 702 }; 703 704 } // namespace iso_manager 705 } // namespace hci 706 } // namespace bluetooth 707