OSDN Git Service

RootCanal: Iso support
authorJakub Pawlowski <jpawlowski@google.com>
Wed, 17 Feb 2021 15:45:41 +0000 (16:45 +0100)
committerJakub Pawlowski <jpawlowski@google.com>
Wed, 24 Feb 2021 21:20:39 +0000 (21:20 +0000)
Add remote_handle to ISO connections.

Tag: #feature
Test: cert/run LeIsoTest
Bug: 177907117
Change-Id: I55cca5f758264c1fb408623ed8a85110076f9bd9

vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl

index 20c5fea..c9052a3 100644 (file)
@@ -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);
-    return false;
+
+  LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
+  return false;
+}
+
+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;
+    }
   }
-  connected_streams_.push_back(config);
-  return true;
+  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);
 }
index d6cf162..feca03c 100644 (file)
@@ -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
index f83b3a0..b8155c9 100644 (file)
@@ -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(
-      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()))));
+
+  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,
+            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) {
-    auto timestamped = bluetooth::hci::IsoWithTimestampView::Create(iso);
-    ASSERT(timestamped.IsValid());
-    uint32_t timestamp = timestamped.GetTimeStamp();
-    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)));
+    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(), 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;
 }
index af03848..0bd600d 100644 (file)
@@ -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){