Loading system/stack/btm/btm_iso_impl.h +8 −7 Original line number Original line Diff line number Diff line Loading @@ -57,7 +57,8 @@ static constexpr uint8_t kStateFlagIsCancelled = 0x20; constexpr char kBtmLogTag[] = "ISO"; constexpr char kBtmLogTag[] = "ISO"; struct iso_sync_info { struct iso_sync_info { uint16_t seq_nb; uint16_t tx_seq_nb; uint16_t rx_seq_nb; }; }; struct iso_base { struct iso_base { Loading Loading @@ -159,7 +160,7 @@ struct iso_impl { auto cis = std::unique_ptr<iso_cis>(new iso_cis()); auto cis = std::unique_ptr<iso_cis>(new iso_cis()); cis->cig_id = cig_id; cis->cig_id = cig_id; cis->sdu_itv = sdu_itv_mtos; cis->sdu_itv = sdu_itv_mtos; cis->sync_info = {.seq_nb = 0}; cis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; cis->used_credits = 0; cis->used_credits = 0; cis->state_flags = kStateFlagsNone; cis->state_flags = kStateFlagsNone; conn_hdl_to_cis_map_[conn_handle] = std::move(cis); conn_hdl_to_cis_map_[conn_handle] = std::move(cis); Loading Loading @@ -528,8 +529,8 @@ struct iso_impl { /* Calculate sequence number for the ISO data packet. /* Calculate sequence number for the ISO data packet. * It should be incremented by 1 every SDU Interval. * It should be incremented by 1 every SDU Interval. */ */ uint16_t seq_nb = iso->sync_info.seq_nb; uint16_t seq_nb = iso->sync_info.tx_seq_nb; iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; iso->sync_info.tx_seq_nb = (seq_nb + 1) & 0xffff; if (iso_credits_ == 0 || data_len > iso_buffer_size_) { if (iso_credits_ == 0 || data_len > iso_buffer_size_) { iso->cr_stats.credits_underflow_bytes += data_len; iso->cr_stats.credits_underflow_bytes += data_len; Loading Loading @@ -681,7 +682,7 @@ struct iso_impl { auto bis = std::unique_ptr<iso_bis>(new iso_bis()); auto bis = std::unique_ptr<iso_bis>(new iso_bis()); bis->big_handle = evt.big_id; bis->big_handle = evt.big_id; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sync_info = {.seq_nb = 0}; bis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; bis->used_credits = 0; bis->used_credits = 0; bis->state_flags = kStateFlagIsBroadcast; bis->state_flags = kStateFlagIsBroadcast; conn_hdl_to_bis_map_[conn_handle] = std::move(bis); conn_hdl_to_bis_map_[conn_handle] = std::move(bis); Loading Loading @@ -806,8 +807,8 @@ struct iso_impl { STREAM_TO_UINT16(seq_nb, stream); STREAM_TO_UINT16(seq_nb, stream); uint16_t expected_seq_nb = iso->sync_info.seq_nb; uint16_t expected_seq_nb = iso->sync_info.rx_seq_nb; iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; iso->sync_info.rx_seq_nb = (seq_nb + 1) & 0xffff; evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; if (evt.evt_lost > 0) { if (evt.evt_lost > 0) { Loading system/stack/test/btm_iso_test.cc +78 −0 Original line number Original line Diff line number Diff line Loading @@ -2085,6 +2085,84 @@ TEST_F(IsoManagerTest, SendIsoDataCigValid) { } } } } TEST_F(IsoManagerTest, SendReceiveIsoDataSequenceNumberCheck) { 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) { bluetooth::hci::iso_manager::iso_data_path_params path_params = kDefaultIsoDataPathParams; path_params.data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionOut; IsoManager::GetInstance()->SetupIsoDataPath(handle, path_params); constexpr uint8_t data_len = 108; uint16_t seq_num = 0xFFFF; EXPECT_CALL(iso_interface_, HciSend) .WillRepeatedly([handle, data_len, &seq_num](BT_HDR* p_msg) { uint8_t* p = p_msg->data; uint16_t msg_handle; uint16_t iso_load_len; ASSERT_NE(p_msg, nullptr); ASSERT_EQ(p_msg->len, data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 12 : 8)); // Verify packet internals STREAM_TO_UINT16(msg_handle, p); ASSERT_EQ(msg_handle, handle); STREAM_TO_UINT16(iso_load_len, p); ASSERT_EQ(iso_load_len, data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 8 : 4)); if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) { STREAM_SKIP_UINT16(p); // skip ts LSB halfword STREAM_SKIP_UINT16(p); // skip ts MSB halfword } // store the seq_nb STREAM_TO_UINT16(seq_num, p); uint16_t msg_data_len; STREAM_TO_UINT16(msg_data_len, p); ASSERT_EQ(msg_data_len, data_len); }) .RetiresOnSaturation(); // Send Iso data and verify the sequence number std::vector<uint8_t> data_vec(data_len, 0); IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); ASSERT_NE(0xFFFF, seq_num); // Check the receiving iso packet // EXPECT_CALL(*cig_callbacks_, OnCisEvent).Times(1); EXPECT_CALL(*cig_callbacks_, OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, _)) .WillOnce([](uint8_t /*evt_code*/, void* event) { bluetooth::hci::iso_manager::cis_data_evt* cis_data_evt = static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(event); // Make sure no event lost is reported due to seq_nb being shared between two // directions ASSERT_EQ(cis_data_evt->evt_lost, 0); }); std::vector<uint8_t> dummy_msg(18); uint8_t* p = dummy_msg.data(); UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_ISO); UINT16_TO_STREAM(p, 10); // .len UINT16_TO_STREAM(p, 0); // .offset UINT16_TO_STREAM(p, 0); // .layer_specific UINT16_TO_STREAM(p, handle); IsoManager::GetInstance()->HandleIsoData(dummy_msg.data()); } } TEST_F(IsoManagerTest, SendIsoDataBigValid) { TEST_F(IsoManagerTest, SendIsoDataBigValid) { IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams); IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams); Loading Loading
system/stack/btm/btm_iso_impl.h +8 −7 Original line number Original line Diff line number Diff line Loading @@ -57,7 +57,8 @@ static constexpr uint8_t kStateFlagIsCancelled = 0x20; constexpr char kBtmLogTag[] = "ISO"; constexpr char kBtmLogTag[] = "ISO"; struct iso_sync_info { struct iso_sync_info { uint16_t seq_nb; uint16_t tx_seq_nb; uint16_t rx_seq_nb; }; }; struct iso_base { struct iso_base { Loading Loading @@ -159,7 +160,7 @@ struct iso_impl { auto cis = std::unique_ptr<iso_cis>(new iso_cis()); auto cis = std::unique_ptr<iso_cis>(new iso_cis()); cis->cig_id = cig_id; cis->cig_id = cig_id; cis->sdu_itv = sdu_itv_mtos; cis->sdu_itv = sdu_itv_mtos; cis->sync_info = {.seq_nb = 0}; cis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; cis->used_credits = 0; cis->used_credits = 0; cis->state_flags = kStateFlagsNone; cis->state_flags = kStateFlagsNone; conn_hdl_to_cis_map_[conn_handle] = std::move(cis); conn_hdl_to_cis_map_[conn_handle] = std::move(cis); Loading Loading @@ -528,8 +529,8 @@ struct iso_impl { /* Calculate sequence number for the ISO data packet. /* Calculate sequence number for the ISO data packet. * It should be incremented by 1 every SDU Interval. * It should be incremented by 1 every SDU Interval. */ */ uint16_t seq_nb = iso->sync_info.seq_nb; uint16_t seq_nb = iso->sync_info.tx_seq_nb; iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; iso->sync_info.tx_seq_nb = (seq_nb + 1) & 0xffff; if (iso_credits_ == 0 || data_len > iso_buffer_size_) { if (iso_credits_ == 0 || data_len > iso_buffer_size_) { iso->cr_stats.credits_underflow_bytes += data_len; iso->cr_stats.credits_underflow_bytes += data_len; Loading Loading @@ -681,7 +682,7 @@ struct iso_impl { auto bis = std::unique_ptr<iso_bis>(new iso_bis()); auto bis = std::unique_ptr<iso_bis>(new iso_bis()); bis->big_handle = evt.big_id; bis->big_handle = evt.big_id; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sdu_itv = last_big_create_req_sdu_itv_; bis->sync_info = {.seq_nb = 0}; bis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0}; bis->used_credits = 0; bis->used_credits = 0; bis->state_flags = kStateFlagIsBroadcast; bis->state_flags = kStateFlagIsBroadcast; conn_hdl_to_bis_map_[conn_handle] = std::move(bis); conn_hdl_to_bis_map_[conn_handle] = std::move(bis); Loading Loading @@ -806,8 +807,8 @@ struct iso_impl { STREAM_TO_UINT16(seq_nb, stream); STREAM_TO_UINT16(seq_nb, stream); uint16_t expected_seq_nb = iso->sync_info.seq_nb; uint16_t expected_seq_nb = iso->sync_info.rx_seq_nb; iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff; iso->sync_info.rx_seq_nb = (seq_nb + 1) & 0xffff; evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff; if (evt.evt_lost > 0) { if (evt.evt_lost > 0) { Loading
system/stack/test/btm_iso_test.cc +78 −0 Original line number Original line Diff line number Diff line Loading @@ -2085,6 +2085,84 @@ TEST_F(IsoManagerTest, SendIsoDataCigValid) { } } } } TEST_F(IsoManagerTest, SendReceiveIsoDataSequenceNumberCheck) { 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) { bluetooth::hci::iso_manager::iso_data_path_params path_params = kDefaultIsoDataPathParams; path_params.data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionOut; IsoManager::GetInstance()->SetupIsoDataPath(handle, path_params); constexpr uint8_t data_len = 108; uint16_t seq_num = 0xFFFF; EXPECT_CALL(iso_interface_, HciSend) .WillRepeatedly([handle, data_len, &seq_num](BT_HDR* p_msg) { uint8_t* p = p_msg->data; uint16_t msg_handle; uint16_t iso_load_len; ASSERT_NE(p_msg, nullptr); ASSERT_EQ(p_msg->len, data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 12 : 8)); // Verify packet internals STREAM_TO_UINT16(msg_handle, p); ASSERT_EQ(msg_handle, handle); STREAM_TO_UINT16(iso_load_len, p); ASSERT_EQ(iso_load_len, data_len + ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) ? 8 : 4)); if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) { STREAM_SKIP_UINT16(p); // skip ts LSB halfword STREAM_SKIP_UINT16(p); // skip ts MSB halfword } // store the seq_nb STREAM_TO_UINT16(seq_num, p); uint16_t msg_data_len; STREAM_TO_UINT16(msg_data_len, p); ASSERT_EQ(msg_data_len, data_len); }) .RetiresOnSaturation(); // Send Iso data and verify the sequence number std::vector<uint8_t> data_vec(data_len, 0); IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), data_vec.size()); ASSERT_NE(0xFFFF, seq_num); // Check the receiving iso packet // EXPECT_CALL(*cig_callbacks_, OnCisEvent).Times(1); EXPECT_CALL(*cig_callbacks_, OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, _)) .WillOnce([](uint8_t /*evt_code*/, void* event) { bluetooth::hci::iso_manager::cis_data_evt* cis_data_evt = static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(event); // Make sure no event lost is reported due to seq_nb being shared between two // directions ASSERT_EQ(cis_data_evt->evt_lost, 0); }); std::vector<uint8_t> dummy_msg(18); uint8_t* p = dummy_msg.data(); UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_ISO); UINT16_TO_STREAM(p, 10); // .len UINT16_TO_STREAM(p, 0); // .offset UINT16_TO_STREAM(p, 0); // .layer_specific UINT16_TO_STREAM(p, handle); IsoManager::GetInstance()->HandleIsoData(dummy_msg.data()); } } TEST_F(IsoManagerTest, SendIsoDataBigValid) { TEST_F(IsoManagerTest, SendIsoDataBigValid) { IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams); IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams); Loading