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

Commit 245b38f9 authored by Myles Watson's avatar Myles Watson
Browse files

RootCanal: Add Iso command support for CIG/CIS

Bug: 163818400
Test: cert/run --host
Tag: #feature
Change-Id: I16ead9bbd66b8fe6e32c0e01dd6841c909079738
parent d0e8ab6a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ cc_library_static {
        "model/controller/acl_connection.cc",
        "model/controller/acl_connection_handler.cc",
        "model/controller/dual_mode_controller.cc",
        "model/controller/isochronous_connection_handler.cc",
        "model/controller/le_advertiser.cc",
        "model/controller/link_layer_controller.cc",
        "model/controller/security_manager.cc",
+156 −2
Original line number Diff line number Diff line
@@ -16,9 +16,10 @@

#include "acl_connection_handler.h"

#include "os/log.h"
#include <hci/hci_packets.h>

#include "hci/address.h"
#include "os/log.h"

using std::shared_ptr;

@@ -33,7 +34,8 @@ bool AclConnectionHandler::HasHandle(uint16_t handle) const {
}

uint16_t AclConnectionHandler::GetUnusedHandle() {
  while (HasHandle(last_handle_)) {
  while (HasHandle(last_handle_) ||
         isochronous_connection_handler_.HasHandle(last_handle_)) {
    last_handle_ = (last_handle_ + 1) % kReservedHandle;
  }
  uint16_t unused_handle = last_handle_;
@@ -193,4 +195,156 @@ Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
  return acl_connections_.at(handle).GetPhyType();
}

std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
AclConnectionHandler::SetCigParameters(
    uint8_t id, uint32_t sdu_interval_m_to_s, uint32_t sdu_interval_s_to_m,
    bluetooth::hci::ClockAccuracy accuracy, bluetooth::hci::Packing packing,
    bluetooth::hci::Enable framed, uint16_t max_transport_latency_m_to_s_,
    uint16_t max_transport_latency_s_to_m_,
    std::vector<bluetooth::hci::CisParametersConfig>& streams) {
  std::vector<uint16_t> handles;
  GroupParameters group_parameters{
      .id = id,
      .sdu_interval_m_to_s = sdu_interval_m_to_s,
      .sdu_interval_s_to_m = sdu_interval_s_to_m,
      .interleaved = packing == bluetooth::hci::Packing::INTERLEAVED,
      .framed = framed == bluetooth::hci::Enable::ENABLED,
      .max_transport_latency_m_to_s = max_transport_latency_m_to_s_,
      .max_transport_latency_s_to_m = max_transport_latency_s_to_m_};
  std::vector<StreamParameters> stream_parameters;
  for (size_t i = 0; i < streams.size(); i++) {
    auto handle = GetUnusedHandle();
    StreamParameters a{.group_id = group_parameters.id,
                       .stream_id = streams[i].cis_id_,
                       .max_sdu_s_to_m = streams[i].max_sdu_s_to_m_,
                       .max_sdu_m_to_s = streams[i].max_sdu_m_to_s_,
                       .handle = handle,
                       .rtn_m_to_s = streams[i].rtn_m_to_s_,
                       .rtn_s_to_m = streams[i].rtn_s_to_m_};
    handles.push_back(handle);
    stream_parameters.push_back(std::move(a));
  }

  return isochronous_connection_handler_.SetCigParameters(
      group_parameters, stream_parameters, std::move(handles));
}

void AclConnectionHandler::CreatePendingCis(
    bluetooth::hci::CreateCisConfig config) {
  pending_streams_.emplace_back(std::move(config));
}

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

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_) {
      pending_streams_.erase(pending_streams_.begin() + position);
      break;
    }
  }
  if (position == pending_streams_.size()) {
    LOG_INFO("No pending connection with handle 0x%hx", handle);
    return false;
  }
  return true;
}

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_;
      break;
    }
  }
  if (position == pending_streams_.size()) {
    LOG_INFO("No pending connection with handle 0x%hx", cis_handle);
  }
  return handle;
}

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_) {
      connected_streams_.erase(connected_streams_.begin() + position);
      break;
    }
  }
  if (position == connected_streams_.size()) {
    LOG_INFO("No connected stream 0x%hx", cis_handle);
    return false;
  }
  return true;
}

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) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
  for (const auto& stream : pending_streams_) {
    if (isochronous_connection_handler_.GetGroupId(
            stream.cis_connection_handle_) == cig_id) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
  auto status = isochronous_connection_handler_.RemoveCig(cig_id);
  if (status == bluetooth::hci::ErrorCode::SUCCESS) {
    // Clean up?
  }
  return status;
}

bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
  for (const auto& config : pending_streams_) {
    if (config.cis_connection_handle_ == handle) {
      return true;
    }
  }
  return false;
}

bool AclConnectionHandler::HasPendingCis() const {
  return !pending_streams_.empty();
}

bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
  return isochronous_connection_handler_.GetStreamIsConnected(handle);
}

bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
  return isochronous_connection_handler_.HasHandle(handle);
}

GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
  return isochronous_connection_handler_.GetGroupParameters(id);
}

StreamParameters AclConnectionHandler::GetStreamParameters(
    uint16_t handle) const {
  return isochronous_connection_handler_.GetStreamParameters(handle);
}

}  // namespace test_vendor_lib
+37 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "acl_connection.h"
#include "hci/address.h"
#include "hci/address_with_type.h"
#include "isochronous_connection_handler.h"
#include "phy.h"

namespace test_vendor_lib {
@@ -63,6 +64,39 @@ class AclConnectionHandler {

  Phy::Type GetPhyType(uint16_t handle) const;

  std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
  SetCigParameters(uint8_t id, uint32_t sdu_interval_m_to_s,
                   uint32_t sdu_interval_s_to_m,
                   bluetooth::hci::ClockAccuracy accuracy,
                   bluetooth::hci::Packing packing,
                   bluetooth::hci::Enable framing,
                   uint16_t max_transport_latency_m_to_s_,
                   uint16_t max_transport_latency_s_to_m_,
                   std::vector<bluetooth::hci::CisParametersConfig>& streams);

  void CreatePendingCis(bluetooth::hci::CreateCisConfig config);

  bool ConnectCis(uint16_t handle);

  uint16_t GetPendingAclHandle(uint16_t cis_handle) const;

  bool RejectCis(uint16_t handle);

  bool DisconnectCis(uint16_t handle);

  bluetooth::hci::ErrorCode RemoveCig(uint8_t cig_id);

  bool HasPendingCis() const;

  bool HasPendingCisConnection(uint16_t handle) const;

  bool HasCisHandle(uint16_t handle) const;

  bool HasConnectedCis(uint16_t handle) const;

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

 private:
  std::unordered_map<uint16_t, AclConnection> acl_connections_;
  bool classic_connection_pending_{false};
@@ -76,6 +110,9 @@ 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_;
};

}  // namespace test_vendor_lib
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>

#include "hci/hci_packets.h"
#include "model/controller/connected_isochronous_stream.h"

namespace test_vendor_lib {

class GroupParameters {
 public:
  uint8_t id;
  uint32_t sdu_interval_m_to_s;
  uint32_t sdu_interval_s_to_m;
  bool interleaved;
  bool framed;
  uint16_t max_transport_latency_m_to_s;
  uint16_t max_transport_latency_s_to_m;
};

class ConnectedIsochronousGroup {
 public:
  ConnectedIsochronousGroup(GroupParameters parameters,
                            std::vector<ConnectedIsochronousStream> streams)
      : parameters_(parameters), streams_(std::move(streams)) {}

  virtual ~ConnectedIsochronousGroup() = default;

  bool HasConnectedStream() const {
    for (auto& stream : streams_) {
      if (stream.IsConnected()) {
        return true;
      }
    }
    return false;
  }

  bool StreamIsConnected(uint16_t handle) const {
    return streams_.at(handle).IsConnected();
  }

  bool HasStreams() const { return !streams_.empty(); }

  GroupParameters GetParameters() const { return parameters_; }

  StreamParameters GetStreamParameters(uint16_t handle) const {
    for (const auto& stream : streams_) {
      if (stream.GetHandle() == handle) {
        return stream.GetConfig();
      }
    }
    return StreamParameters{};
  }

 private:
  GroupParameters parameters_;
  std::vector<ConnectedIsochronousStream> streams_;
};

}  // namespace test_vendor_lib
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>

#include "hci/hci_packets.h"

namespace test_vendor_lib {

class StreamParameters {
 public:
  uint8_t group_id;
  uint8_t stream_id;
  uint16_t max_sdu_m_to_s;
  uint16_t max_sdu_s_to_m;
  uint8_t rtn_m_to_s;
  uint8_t rtn_s_to_m;
  uint16_t handle;
};

class ConnectedIsochronousStream {
 public:
  ConnectedIsochronousStream(StreamParameters& stream_param)
      : config_(stream_param) {}

  virtual ~ConnectedIsochronousStream() = default;

  bool IsConnected() const { return is_connected_; }
  StreamParameters GetConfig() const { return config_; }

  uint16_t GetHandle() const { return config_.handle; }
  void Connect() { is_connected_ = true; }

  void Disconnect() { is_connected_ = false; }

 private:
  bool is_connected_{false};
  StreamParameters config_;
};
}  // namespace test_vendor_lib
Loading