Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 467771ca authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "IsoManager: Fix sequence numbers for bidirectional CISes" into main

parents 21aff437 9e813d44
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ static constexpr uint8_t kStateFlagIsCancelled = 0x20;
constexpr char kBtmLogTag[] = "ISO";

struct iso_sync_info {
  uint16_t seq_nb;
  uint16_t tx_seq_nb;
  uint16_t rx_seq_nb;
};

struct iso_base {
@@ -159,7 +160,7 @@ struct iso_impl {
        auto cis = std::unique_ptr<iso_cis>(new iso_cis());
        cis->cig_id = cig_id;
        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->state_flags = kStateFlagsNone;
        conn_hdl_to_cis_map_[conn_handle] = std::move(cis);
@@ -528,8 +529,8 @@ struct iso_impl {
    /* Calculate sequence number for the ISO data packet.
     * It should be incremented by 1 every SDU Interval.
     */
    uint16_t seq_nb = iso->sync_info.seq_nb;
    iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff;
    uint16_t seq_nb = iso->sync_info.tx_seq_nb;
    iso->sync_info.tx_seq_nb = (seq_nb + 1) & 0xffff;

    if (iso_credits_ == 0 || data_len > iso_buffer_size_) {
      iso->cr_stats.credits_underflow_bytes += data_len;
@@ -681,7 +682,7 @@ struct iso_impl {
        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 = {.seq_nb = 0};
        bis->sync_info = {.tx_seq_nb = 0, .rx_seq_nb = 0};
        bis->used_credits = 0;
        bis->state_flags = kStateFlagIsBroadcast;
        conn_hdl_to_bis_map_[conn_handle] = std::move(bis);
@@ -806,8 +807,8 @@ struct iso_impl {

    STREAM_TO_UINT16(seq_nb, stream);

    uint16_t expected_seq_nb = iso->sync_info.seq_nb;
    iso->sync_info.seq_nb = (seq_nb + 1) & 0xffff;
    uint16_t expected_seq_nb = iso->sync_info.rx_seq_nb;
    iso->sync_info.rx_seq_nb = (seq_nb + 1) & 0xffff;

    evt.evt_lost = ((1 << 16) + seq_nb - expected_seq_nb) & 0xffff;
    if (evt.evt_lost > 0) {
+78 −0
Original line number Diff line number Diff line
@@ -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) {
  IsoManager::GetInstance()->CreateBig(volatile_test_big_params_evt_.big_id, kDefaultBigParams);