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

Commit 7e50976b authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

RootCanal: Iso support

Add remote_handle to ISO connections.

Tag: #feature
Test: cert/run LeIsoTest
Bug: 177907117
Change-Id: I55cca5f758264c1fb408623ed8a85110076f9bd9
parent df76cc1e
Loading
Loading
Loading
Loading
+74 −20
Original line number Diff line number Diff line
@@ -229,31 +229,50 @@ AclConnectionHandler::SetCigParameters(

void AclConnectionHandler::CreatePendingCis(
    bluetooth::hci::CreateCisConfig config) {
  pending_streams_.emplace_back(std::move(config));
  CisHandles handles;
  handles.cis_handle_ = config.cis_connection_handle_;
  handles.acl_handle_ = config.acl_connection_handle_;
  handles.remote_cis_handle_ = kReservedHandle;
  pending_streams_.emplace_back(std::move(handles));
}

bool AclConnectionHandler::ConnectCis(uint16_t handle) {
  size_t position;
  bluetooth::hci::CreateCisConfig config;
  CisHandles connection;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_connection_handle_) {
      config = pending_streams_[position];
    if (handle == pending_streams_[position].cis_handle_) {
      LOG_INFO("Found handle 0x%04hx", handle);
      connection = pending_streams_[position];
      pending_streams_.erase(pending_streams_.begin() + position);
      break;
      connected_streams_.push_back(connection);
      ASSERT(connection.cis_handle_ != kReservedHandle);
      ASSERT(connection.acl_handle_ != kReservedHandle);
      ASSERT(connection.remote_cis_handle_ != kReservedHandle);
      return true;
    }
  }
  if (position == pending_streams_.size()) {
    LOG_INFO("No pending connection with handle 0x%hx", handle);

  LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
  return false;
}
  connected_streams_.push_back(config);
  return true;

void AclConnectionHandler::SetRemoteCisHandle(uint16_t handle,
                                              uint16_t remote_handle) {
  for (size_t position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_handle_) {
      LOG_INFO("Added remote handle 0x%04hx to handle 0x%04hx", remote_handle,
               pending_streams_[position].cis_handle_);
      pending_streams_[position].remote_cis_handle_ = remote_handle;
      return;
    }
  }
  LOG_INFO("Couldn't find CIS connection with handle 0x%04hx", handle);
}

bool AclConnectionHandler::RejectCis(uint16_t handle) {
  size_t position;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_connection_handle_) {
    if (handle == pending_streams_[position].cis_handle_) {
      pending_streams_.erase(pending_streams_.begin() + position);
      break;
    }
@@ -269,8 +288,8 @@ uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
  size_t position;
  uint16_t handle = 0xffff;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (cis_handle == pending_streams_[position].cis_connection_handle_) {
      handle = pending_streams_[position].acl_connection_handle_;
    if (cis_handle == pending_streams_[position].cis_handle_) {
      handle = pending_streams_[position].acl_handle_;
      break;
    }
  }
@@ -283,7 +302,7 @@ uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {
  size_t position;
  for (position = 0; position < connected_streams_.size(); position++) {
    if (cis_handle == connected_streams_[position].cis_connection_handle_) {
    if (cis_handle == connected_streams_[position].cis_handle_) {
      connected_streams_.erase(connected_streams_.begin() + position);
      break;
    }
@@ -297,14 +316,14 @@ bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {

bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {
  for (const auto& stream : connected_streams_) {
    if (isochronous_connection_handler_.GetGroupId(
            stream.cis_connection_handle_) == cig_id) {
    if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
        cig_id) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
  for (const auto& stream : pending_streams_) {
    if (isochronous_connection_handler_.GetGroupId(
            stream.cis_connection_handle_) == cig_id) {
    if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
        cig_id) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
@@ -317,7 +336,7 @@ bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {

bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
  for (const auto& config : pending_streams_) {
    if (config.cis_connection_handle_ == handle) {
    if (config.cis_handle_ == handle) {
      return true;
    }
  }
@@ -329,13 +348,48 @@ bool AclConnectionHandler::HasPendingCis() const {
}

bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
  return isochronous_connection_handler_.GetStreamIsConnected(handle);
  for (const auto& cs : connected_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  return false;
}

bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
  for (const auto& cs : pending_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  for (const auto& cs : connected_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  return isochronous_connection_handler_.HasHandle(handle);
}

uint16_t AclConnectionHandler::GetAclHandleForCisHandle(
    uint16_t cis_handle) const {
  for (const auto& cs : connected_streams_) {
    if (cis_handle == cs.cis_handle_) {
      return cs.acl_handle_;
    }
  }
  return kReservedHandle;
}

uint16_t AclConnectionHandler::GetRemoteCisHandleForCisHandle(
    uint16_t cis_handle) const {
  for (const auto& cs : connected_streams_) {
    if (cis_handle == cs.cis_handle_) {
      return cs.remote_cis_handle_;
    }
  }
  return kReservedHandle;
}

GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
  return isochronous_connection_handler_.GetGroupParameters(id);
}
+12 −2
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ class AclConnectionHandler {

  bool ConnectCis(uint16_t handle);

  void SetRemoteCisHandle(uint16_t handle, uint16_t remote_handle);

  uint16_t GetPendingAclHandle(uint16_t cis_handle) const;

  bool RejectCis(uint16_t handle);
@@ -94,6 +96,9 @@ class AclConnectionHandler {

  bool HasConnectedCis(uint16_t handle) const;

  uint16_t GetAclHandleForCisHandle(uint16_t cis_handle) const;
  uint16_t GetRemoteCisHandleForCisHandle(uint16_t cis_handle) const;

  StreamParameters GetStreamParameters(uint16_t handle) const;
  GroupParameters GetGroupParameters(uint8_t id) const;

@@ -111,8 +116,13 @@ class AclConnectionHandler {
  uint16_t GetUnusedHandle();
  uint16_t last_handle_{kReservedHandle - 2};
  IsochronousConnectionHandler isochronous_connection_handler_;
  std::vector<bluetooth::hci::CreateCisConfig> connected_streams_;
  std::vector<bluetooth::hci::CreateCisConfig> pending_streams_;
  struct CisHandles {
    uint16_t acl_handle_ = kReservedHandle;
    uint16_t cis_handle_ = kReservedHandle;
    uint16_t remote_cis_handle_ = kReservedHandle;
  };
  std::vector<CisHandles> connected_streams_;
  std::vector<CisHandles> pending_streams_;
};

}  // namespace test_vendor_lib
+109 −33
Original line number Diff line number Diff line
@@ -852,11 +852,49 @@ void LinkLayerController::IncomingIsoPacket(LinkLayerPacketView incoming) {
    LOG_INFO("Dropping ISO packet to a disconnected handle 0x%hx", cis_handle);
    return;
  }
  send_iso_(bluetooth::hci::IsoBuilder::Create(

  auto sc = iso.GetSc();
  switch (sc) {
    case StartContinuation::START: {
      auto iso_start = IsoStartView::Create(iso);
      ASSERT(iso_start.IsValid());
      if (iso.GetCmplt() == Complete::COMPLETE) {
        send_iso_(bluetooth::hci::IsoWithoutTimestampBuilder::Create(
            cis_handle, bluetooth::hci::IsoPacketBoundaryFlag::COMPLETE_SDU,
      bluetooth::hci::TimeStampFlag::PRESENT,
      std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
          iso.GetPayload().begin(), iso.GetPayload().end()))));
            0 /* seq num */, bluetooth::hci::IsoPacketStatusFlag::VALID,
            std::make_unique<bluetooth::packet::RawBuilder>(
                std::vector<uint8_t>(iso_start.GetPayload().begin(),
                                     iso_start.GetPayload().end()))));
      } else {
        send_iso_(bluetooth::hci::IsoWithoutTimestampBuilder::Create(
            cis_handle, bluetooth::hci::IsoPacketBoundaryFlag::FIRST_FRAGMENT,
            0 /* seq num */, bluetooth::hci::IsoPacketStatusFlag::VALID,
            std::make_unique<bluetooth::packet::RawBuilder>(
                std::vector<uint8_t>(iso_start.GetPayload().begin(),
                                     iso_start.GetPayload().end()))));
      }
    } break;
    case StartContinuation::CONTINUATION: {
      auto continuation = IsoContinuationView::Create(iso);
      ASSERT(continuation.IsValid());
      if (iso.GetCmplt() == Complete::COMPLETE) {
        send_iso_(bluetooth::hci::IsoWithoutTimestampBuilder::Create(
            cis_handle, bluetooth::hci::IsoPacketBoundaryFlag::LAST_FRAGMENT,
            0 /* seq num */, bluetooth::hci::IsoPacketStatusFlag::VALID,
            std::make_unique<bluetooth::packet::RawBuilder>(
                std::vector<uint8_t>(continuation.GetPayload().begin(),
                                     continuation.GetPayload().end()))));
      } else {
        send_iso_(bluetooth::hci::IsoWithoutTimestampBuilder::Create(
            cis_handle,
            bluetooth::hci::IsoPacketBoundaryFlag::CONTINUATION_FRAGMENT,
            0 /* seq num */, bluetooth::hci::IsoPacketStatusFlag::VALID,
            std::make_unique<bluetooth::packet::RawBuilder>(
                std::vector<uint8_t>(continuation.GetPayload().begin(),
                                     continuation.GetPayload().end()))));
      }
    } break;
  }
}

void LinkLayerController::HandleIso(bluetooth::hci::IsoView iso) {
@@ -870,9 +908,9 @@ void LinkLayerController::HandleIso(bluetooth::hci::IsoView iso) {
    return;
  }

  auto stream_parameters = connections_.GetStreamParameters(cis_handle);
  auto acl_handle = stream_parameters.handle;
  uint16_t remote_handle = kReservedHandle;  // TODO: Decide how to handle this
  auto acl_handle = connections_.GetAclHandleForCisHandle(cis_handle);
  uint16_t remote_handle =
      connections_.GetRemoteCisHandleForCisHandle(cis_handle);
  model::packets::StartContinuation start_flag =
      model::packets::StartContinuation::START;
  model::packets::Complete complete_flag = model::packets::Complete::COMPLETE;
@@ -894,25 +932,44 @@ void LinkLayerController::HandleIso(bluetooth::hci::IsoView iso) {
      complete_flag = model::packets::Complete::INCOMPLETE;
      break;
  }
  std::unique_ptr<bluetooth::packet::RawBuilder> payload =
      std::make_unique<bluetooth::packet::RawBuilder>();
  for (const auto& it : iso.GetPayload()) {
    payload->AddOctets1(it);
  }
  if (start_flag == model::packets::StartContinuation::START) {
    if (iso.GetTsFlag() == bluetooth::hci::TimeStampFlag::PRESENT) {
      auto timestamped = bluetooth::hci::IsoWithTimestampView::Create(iso);
      ASSERT(timestamped.IsValid());
      uint32_t timestamp = timestamped.GetTimeStamp();
      std::unique_ptr<bluetooth::packet::RawBuilder> payload =
          std::make_unique<bluetooth::packet::RawBuilder>();
      for (const auto it : timestamped.GetPayload()) {
        payload->AddOctets1(it);
      }

      SendLeLinkLayerPacket(model::packets::IsoStartBuilder::Create(
          connections_.GetOwnAddress(acl_handle).GetAddress(),
        connections_.GetAddress(acl_handle).GetAddress(), acl_handle,
        remote_handle, complete_flag, timestamp, std::move(payload)));
          connections_.GetAddress(acl_handle).GetAddress(), remote_handle,
          complete_flag, timestamp, std::move(payload)));
    } else {
      auto pkt = bluetooth::hci::IsoWithoutTimestampView::Create(iso);
      ASSERT(pkt.IsValid());

      auto payload =
          std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
              pkt.GetPayload().begin(), pkt.GetPayload().end()));

      SendLeLinkLayerPacket(model::packets::IsoStartBuilder::Create(
          connections_.GetOwnAddress(acl_handle).GetAddress(),
          connections_.GetAddress(acl_handle).GetAddress(), remote_handle,
          complete_flag, 0, std::move(payload)));
    }
  } else {
    auto pkt = bluetooth::hci::IsoWithoutTimestampView::Create(iso);
    ASSERT(pkt.IsValid());
    std::unique_ptr<bluetooth::packet::RawBuilder> payload =
        std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
            pkt.GetPayload().begin(), pkt.GetPayload().end()));
    SendLeLinkLayerPacket(model::packets::IsoContinuationBuilder::Create(
        connections_.GetOwnAddress(acl_handle).GetAddress(),
        connections_.GetAddress(acl_handle).GetAddress(), acl_handle,
        remote_handle, complete_flag, std::move(payload)));
        connections_.GetAddress(acl_handle).GetAddress(), remote_handle,
        complete_flag, std::move(payload)));
  }
}

@@ -933,18 +990,12 @@ void LinkLayerController::IncomingIsoConnectionRequestPacket(
  /* CIG should be created by the local host before use */
  bluetooth::hci::CreateCisConfig config;
  config.cis_connection_handle_ = req.GetRequesterCisHandle();
  if (!connections_.HasCisHandle(config.cis_connection_handle_)) {
    LOG_INFO("Rejecting connection request to unknown CIS handle 0x%0hx",
             config.cis_connection_handle_);
    SendLeLinkLayerPacket(model::packets::IsoConnectionResponseBuilder::Create(
        incoming.GetDestinationAddress(), incoming.GetSourceAddress(),
        static_cast<uint8_t>(ErrorCode::INVALID_LMP_OR_LL_PARAMETERS),
        config.acl_connection_handle_, config.cis_connection_handle_));
    return;
  }

  config.acl_connection_handle_ =
      connections_.GetHandleOnlyAddress(incoming.GetSourceAddress());
  connections_.CreatePendingCis(config);
  connections_.SetRemoteCisHandle(config.cis_connection_handle_,
                                  req.GetRequesterCisHandle());
  send_event_(bluetooth::hci::LeCisRequestBuilder::Create(
      config.acl_connection_handle_, config.cis_connection_handle_, group_id,
      req.GetId()));
@@ -971,6 +1022,8 @@ void LinkLayerController::IncomingIsoConnectionResponsePacket(
        bluetooth::hci::SecondaryPhyType::NO_PACKETS, 0, 0, 0, 0, 0, 0, 0, 0));
    return;
  }
  connections_.SetRemoteCisHandle(config.cis_connection_handle_,
                                  response.GetResponderCisHandle());
  connections_.ConnectCis(config.cis_connection_handle_);
  auto stream_parameters =
      connections_.GetStreamParameters(config.cis_connection_handle_);
@@ -2632,11 +2685,34 @@ ErrorCode LinkLayerController::LeAcceptCisRequest(uint16_t cis_handle) {
  }
  auto acl_handle = connections_.GetPendingAclHandle(cis_handle);

  connections_.ConnectCis(cis_handle);

  SendLeLinkLayerPacket(model::packets::IsoConnectionResponseBuilder::Create(
      connections_.GetOwnAddress(acl_handle).GetAddress(),
      connections_.GetAddress(acl_handle).GetAddress(),
      static_cast<uint8_t>(ErrorCode::SUCCESS), cis_handle, acl_handle));
      static_cast<uint8_t>(ErrorCode::SUCCESS), cis_handle, acl_handle,
      connections_.GetRemoteCisHandleForCisHandle(cis_handle)));

  // Both sides have to send LeCisEstablished event

  uint32_t cig_sync_delay = 0x100;
  uint32_t cis_sync_delay = 0x200;
  uint32_t latency_m_to_s = 0x200;
  uint32_t latency_s_to_m = 0x200;
  uint8_t nse = 1;
  uint8_t bn_m_to_s = 0;
  uint8_t bn_s_to_m = 0;
  uint8_t ft_m_to_s = 0;
  uint8_t ft_s_to_m = 0;
  uint8_t max_pdu_m_to_s = 0x40;
  uint8_t max_pdu_s_to_m = 0x40;
  uint16_t iso_interval = 0x100;
  send_event_(bluetooth::hci::LeCisEstablishedBuilder::Create(
      ErrorCode::SUCCESS, cis_handle, cig_sync_delay, cis_sync_delay,
      latency_m_to_s, latency_s_to_m,
      bluetooth::hci::SecondaryPhyType::NO_PACKETS,
      bluetooth::hci::SecondaryPhyType::NO_PACKETS, nse, bn_m_to_s, bn_s_to_m,
      ft_m_to_s, ft_s_to_m, max_pdu_m_to_s, max_pdu_s_to_m, iso_interval));
  return ErrorCode::SUCCESS;
}

@@ -2650,7 +2726,7 @@ ErrorCode LinkLayerController::LeRejectCisRequest(uint16_t cis_handle,
  SendLeLinkLayerPacket(model::packets::IsoConnectionResponseBuilder::Create(
      connections_.GetOwnAddress(acl_handle).GetAddress(),
      connections_.GetAddress(acl_handle).GetAddress(),
      static_cast<uint8_t>(reason), acl_handle, cis_handle));
      static_cast<uint8_t>(reason), acl_handle, cis_handle, kReservedHandle));
  connections_.RejectCis(cis_handle);
  return ErrorCode::SUCCESS;
}
+3 −2
Original line number Diff line number Diff line
@@ -262,8 +262,6 @@ enum Complete : 1 {
packet IsoDataPacket : LinkLayerPacket (type = ISO) {
  handle : 12,
  _reserved_ : 4,
  remote_handle : 12,
  _reserved_ : 4,
  sc : StartContinuation,
  cmplt : Complete,
  _reserved_ : 6,
@@ -307,6 +305,9 @@ packet IsoConnectionResponse : LinkLayerPacket (type = ISO_CONNECTION_RESPONSE)
  _reserved_ : 4,
  requester_acl_handle : 12,
  _reserved_ : 4,
  // For the link layer
  responder_cis_handle : 12,
  _reserved_ : 4,
}

packet OobData : LinkLayerPacket (type = OOB_DATA){