Loading system/stack/btm/btm_iso_impl.h +44 −17 Original line number Diff line number Diff line Loading @@ -60,8 +60,9 @@ struct iso_base { }; struct iso_sync_info sync_info; uint8_t state_flags; std::atomic_uint8_t state_flags; uint32_t sdu_itv; std::atomic_uint16_t used_credits; }; typedef iso_base iso_cis; Loading Loading @@ -121,11 +122,14 @@ struct iso_impl { STREAM_TO_UINT16(conn_handle, stream); evt.conn_handles.push_back(conn_handle); conn_hdl_to_cis_map_[conn_handle] = std::unique_ptr<iso_cis>( new iso_cis({.sync_info = {.first_sync_ts = 0, .seq_nb = 0}, .cig_id = cig_id, .state_flags = kStateFlagsNone, .sdu_itv = sdu_itv_mtos})); auto cis = std::unique_ptr<iso_cis>(new iso_cis()); cis->cig_id = cig_id; cis->sdu_itv = sdu_itv_mtos; cis->sync_info = {.first_sync_ts = 0, .seq_nb = 0}; cis->used_credits = 0; cis->state_flags = kStateFlagsNone; conn_hdl_to_cis_map_[conn_handle] = std::move(cis); } } Loading Loading @@ -434,6 +438,7 @@ struct iso_impl { } iso_credits_--; iso->used_credits++; BT_HDR* packet = prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len); Loading Loading @@ -495,6 +500,11 @@ struct iso_impl { cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); cis->state_flags &= ~kStateFlagIsConnected; /* return used credits */ iso_credits_ += cis->used_credits; cis->used_credits = 0; /* Data path is considered still valid, but can be reconfigured only once * CIS is reestablished. */ Loading @@ -514,21 +524,36 @@ struct iso_impl { STREAM_TO_UINT16(handle, p); STREAM_TO_UINT16(num_sent, p); if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) auto iter = conn_hdl_to_cis_map_.find(handle); if (iter != conn_hdl_to_cis_map_.end()) { iter->second->used_credits -= num_sent; iso_credits_ += num_sent; continue; } iter = conn_hdl_to_bis_map_.find(handle); if (iter != conn_hdl_to_bis_map_.end()) { iter->second->used_credits -= num_sent; iso_credits_ += num_sent; continue; } } } void handle_gd_num_completed_pkts(uint16_t handle, uint16_t credits) { if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) auto iter = conn_hdl_to_cis_map_.find(handle); if (iter != conn_hdl_to_cis_map_.end()) { iter->second->used_credits -= credits; iso_credits_ += credits; return; } iter = conn_hdl_to_bis_map_.find(handle); if (iter != conn_hdl_to_bis_map_.end()) { iter->second->used_credits -= credits; iso_credits_ += credits; } } void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_create_cmpl_evt evt; Loading Loading @@ -563,11 +588,13 @@ struct iso_impl { LOG_INFO(" received BIS conn_hdl %d", +conn_handle); if (evt.status == HCI_SUCCESS) { conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>( new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0}, .big_handle = evt.big_id, .state_flags = kStateFlagIsBroadcast, .sdu_itv = last_big_create_req_sdu_itv_})); auto bis = std::unique_ptr<iso_bis>(new iso_bis()); bis->big_handle = evt.big_id; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sync_info = {.first_sync_ts = ts, .seq_nb = 0}; bis->used_credits = 0; bis->state_flags = kStateFlagIsBroadcast; conn_hdl_to_bis_map_[conn_handle] = std::move(bis); } } Loading system/stack/test/btm_iso_test.cc +40 −0 Original line number Diff line number Diff line Loading @@ -2059,6 +2059,46 @@ TEST_F(IsoManagerTest, SendIsoDataCreditsReturned) { } } TEST_F(IsoManagerTest, SendIsoDataCreditsReturnedByDisconnection) { uint8_t num_buffers = controller_interface_.GetIsoBufferCount(); std::vector<uint8_t> data_vec(108, 0); // Check on CIG IsoManager::GetInstance()->CreateCig( volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); bluetooth::hci::iso_manager::cis_establish_params params; for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { params.conn_pairs.push_back({handle, 1}); } IsoManager::GetInstance()->EstablishCis(params); for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { IsoManager::GetInstance()->SetupIsoDataPath(handle, kDefaultIsoDataPathParams); } /* Sending lot of ISO data to first ISO and getting all the credits */ EXPECT_CALL(bte_interface_, HciSend).Times(num_buffers).RetiresOnSaturation(); for (uint8_t i = 0; i < num_buffers; i++) { IsoManager::GetInstance()->SendIsoData( volatile_test_cig_create_cmpl_evt_.conn_handles[0], data_vec.data(), data_vec.size()); } /* Return all credits by disconnecting CIS */ IsoManager::GetInstance()->HandleDisconnect( volatile_test_cig_create_cmpl_evt_.conn_handles[0], 16); /* Try to send ISO data on the second ISO. Expect credits being available.*/ EXPECT_CALL(bte_interface_, HciSend).Times(num_buffers).RetiresOnSaturation(); for (uint8_t i = 0; i < num_buffers; i++) { IsoManager::GetInstance()->SendIsoData( volatile_test_cig_create_cmpl_evt_.conn_handles[1], data_vec.data(), data_vec.size()); } } TEST_F(IsoManagerDeathTest, SendIsoDataWithNoDataPath) { std::vector<uint8_t> data_vec(108, 0); Loading Loading
system/stack/btm/btm_iso_impl.h +44 −17 Original line number Diff line number Diff line Loading @@ -60,8 +60,9 @@ struct iso_base { }; struct iso_sync_info sync_info; uint8_t state_flags; std::atomic_uint8_t state_flags; uint32_t sdu_itv; std::atomic_uint16_t used_credits; }; typedef iso_base iso_cis; Loading Loading @@ -121,11 +122,14 @@ struct iso_impl { STREAM_TO_UINT16(conn_handle, stream); evt.conn_handles.push_back(conn_handle); conn_hdl_to_cis_map_[conn_handle] = std::unique_ptr<iso_cis>( new iso_cis({.sync_info = {.first_sync_ts = 0, .seq_nb = 0}, .cig_id = cig_id, .state_flags = kStateFlagsNone, .sdu_itv = sdu_itv_mtos})); auto cis = std::unique_ptr<iso_cis>(new iso_cis()); cis->cig_id = cig_id; cis->sdu_itv = sdu_itv_mtos; cis->sync_info = {.first_sync_ts = 0, .seq_nb = 0}; cis->used_credits = 0; cis->state_flags = kStateFlagsNone; conn_hdl_to_cis_map_[conn_handle] = std::move(cis); } } Loading Loading @@ -434,6 +438,7 @@ struct iso_impl { } iso_credits_--; iso->used_credits++; BT_HDR* packet = prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len); Loading Loading @@ -495,6 +500,11 @@ struct iso_impl { cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt); cis->state_flags &= ~kStateFlagIsConnected; /* return used credits */ iso_credits_ += cis->used_credits; cis->used_credits = 0; /* Data path is considered still valid, but can be reconfigured only once * CIS is reestablished. */ Loading @@ -514,21 +524,36 @@ struct iso_impl { STREAM_TO_UINT16(handle, p); STREAM_TO_UINT16(num_sent, p); if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) auto iter = conn_hdl_to_cis_map_.find(handle); if (iter != conn_hdl_to_cis_map_.end()) { iter->second->used_credits -= num_sent; iso_credits_ += num_sent; continue; } iter = conn_hdl_to_bis_map_.find(handle); if (iter != conn_hdl_to_bis_map_.end()) { iter->second->used_credits -= num_sent; iso_credits_ += num_sent; continue; } } } void handle_gd_num_completed_pkts(uint16_t handle, uint16_t credits) { if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) auto iter = conn_hdl_to_cis_map_.find(handle); if (iter != conn_hdl_to_cis_map_.end()) { iter->second->used_credits -= credits; iso_credits_ += credits; return; } iter = conn_hdl_to_bis_map_.find(handle); if (iter != conn_hdl_to_bis_map_.end()) { iter->second->used_credits -= credits; iso_credits_ += credits; } } void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_create_cmpl_evt evt; Loading Loading @@ -563,11 +588,13 @@ struct iso_impl { LOG_INFO(" received BIS conn_hdl %d", +conn_handle); if (evt.status == HCI_SUCCESS) { conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>( new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0}, .big_handle = evt.big_id, .state_flags = kStateFlagIsBroadcast, .sdu_itv = last_big_create_req_sdu_itv_})); auto bis = std::unique_ptr<iso_bis>(new iso_bis()); bis->big_handle = evt.big_id; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sync_info = {.first_sync_ts = ts, .seq_nb = 0}; bis->used_credits = 0; bis->state_flags = kStateFlagIsBroadcast; conn_hdl_to_bis_map_[conn_handle] = std::move(bis); } } Loading
system/stack/test/btm_iso_test.cc +40 −0 Original line number Diff line number Diff line Loading @@ -2059,6 +2059,46 @@ TEST_F(IsoManagerTest, SendIsoDataCreditsReturned) { } } TEST_F(IsoManagerTest, SendIsoDataCreditsReturnedByDisconnection) { uint8_t num_buffers = controller_interface_.GetIsoBufferCount(); std::vector<uint8_t> data_vec(108, 0); // Check on CIG IsoManager::GetInstance()->CreateCig( volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); bluetooth::hci::iso_manager::cis_establish_params params; for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { params.conn_pairs.push_back({handle, 1}); } IsoManager::GetInstance()->EstablishCis(params); for (auto& handle : volatile_test_cig_create_cmpl_evt_.conn_handles) { IsoManager::GetInstance()->SetupIsoDataPath(handle, kDefaultIsoDataPathParams); } /* Sending lot of ISO data to first ISO and getting all the credits */ EXPECT_CALL(bte_interface_, HciSend).Times(num_buffers).RetiresOnSaturation(); for (uint8_t i = 0; i < num_buffers; i++) { IsoManager::GetInstance()->SendIsoData( volatile_test_cig_create_cmpl_evt_.conn_handles[0], data_vec.data(), data_vec.size()); } /* Return all credits by disconnecting CIS */ IsoManager::GetInstance()->HandleDisconnect( volatile_test_cig_create_cmpl_evt_.conn_handles[0], 16); /* Try to send ISO data on the second ISO. Expect credits being available.*/ EXPECT_CALL(bte_interface_, HciSend).Times(num_buffers).RetiresOnSaturation(); for (uint8_t i = 0; i < num_buffers; i++) { IsoManager::GetInstance()->SendIsoData( volatile_test_cig_create_cmpl_evt_.conn_handles[1], data_vec.data(), data_vec.size()); } } TEST_F(IsoManagerDeathTest, SendIsoDataWithNoDataPath) { std::vector<uint8_t> data_vec(108, 0); Loading