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;
}
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;
}
}
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;
}
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;
}
}
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;
}
}
}
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);
}
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) {
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;
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)));
}
}
/* 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()));
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_);
}
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;
}
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;
}