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

Commit 3cbd5829 authored by Chris Manton's avatar Chris Manton Committed by android-build-merger
Browse files

Merge "Synchronize l2cap channel for client apps"

am: fe4ceae0

Change-Id: I760e8dbba7c26461c17810b6df16b4a473c2a287
parents b9577ed3 fe4ceae0
Loading
Loading
Loading
Loading
+50 −20
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <memory>
#include <mutex>
#include <queue>
#include <set>
#include <unordered_map>
#include <vector>

@@ -156,6 +157,8 @@ class ConnectionInterface {
struct ConnectionInterfaceManager {
 public:
  ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  ConnectionInterfaceDescriptor AddChannel(ConnectionInterfaceDescriptor cid,
                                           std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  void RemoveConnection(ConnectionInterfaceDescriptor cid);

  void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
@@ -181,40 +184,57 @@ struct ConnectionInterfaceManager {
    // There may be multiple, so only remove one
  }

  void ConnectionFailed(hci::Address address, l2cap::Psm psm) {
  void ConnectionFailed(ConnectionOpenCallback on_open, hci::Address address, l2cap::Psm psm) {
    LOG_DEBUG("Connection Failed");
    // TODO(cmanton) queue this pending connection address/psm tuple up for deletion
    // There may be multiple, so only remove one
    handler_->Post(common::BindOnce(&ConnectionInterfaceManager::GeneralCallback, common::Unretained(this), on_open,
                                    address, psm, kInvalidConnectionInterfaceDescriptor));
  }

  ConnectionInterfaceManager(os::Handler* handler);

  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
  void FreeConnectionInterfaceDescriptor(ConnectionInterfaceDescriptor cid);

 private:
  os::Handler* handler_;
  ConnectionInterfaceDescriptor current_connection_interface_descriptor_;

  bool HasResources() const;
  bool Exists(ConnectionInterfaceDescriptor id) const;
  bool ChannelExists(ConnectionInterfaceDescriptor id) const;
  bool CidExists(ConnectionInterfaceDescriptor id) const;

  std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
  std::set<ConnectionInterfaceDescriptor> active_cid_set_;

  ConnectionInterfaceManager() = delete;
};

ConnectionInterfaceManager::ConnectionInterfaceManager(os::Handler* handler)
    : handler_(handler), current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}

bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
bool ConnectionInterfaceManager::ChannelExists(ConnectionInterfaceDescriptor cid) const {
  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
}

bool ConnectionInterfaceManager::CidExists(ConnectionInterfaceDescriptor cid) const {
  return active_cid_set_.find(cid) != active_cid_set_.end();
}

void ConnectionInterfaceManager::FreeConnectionInterfaceDescriptor(ConnectionInterfaceDescriptor cid) {
  ASSERT(CidExists(cid));
  active_cid_set_.erase(cid);
}

ConnectionInterfaceDescriptor ConnectionInterfaceManager::AllocateConnectionInterfaceDescriptor() {
  ASSERT(HasResources());
  while (Exists(current_connection_interface_descriptor_)) {
  while (CidExists(current_connection_interface_descriptor_)) {
    if (++current_connection_interface_descriptor_ == kInvalidConnectionInterfaceDescriptor) {
      current_connection_interface_descriptor_ = kStartConnectionInterfaceDescriptor;
    }
  }
  active_cid_set_.insert(current_connection_interface_descriptor_);
  return current_connection_interface_descriptor_++;
}

@@ -224,7 +244,11 @@ ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
    return kInvalidConnectionInterfaceDescriptor;
  }
  ConnectionInterfaceDescriptor cid = AllocateConnectionInterfaceDescriptor();
  return AddChannel(cid, std::move(channel));
}

ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
    ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
  auto channel_interface = std::make_unique<ConnectionInterface>(cid, std::move(channel), handler_);
  cid_to_interface_map_[cid] = std::move(channel_interface);
  return cid;
@@ -234,6 +258,7 @@ void ConnectionInterfaceManager::RemoveConnection(ConnectionInterfaceDescriptor
  ASSERT(cid_to_interface_map_.count(cid) == 1);
  cid_to_interface_map_.find(cid)->second->Close();
  cid_to_interface_map_.erase(cid);
  FreeConnectionInterfaceDescriptor(cid);
}

bool ConnectionInterfaceManager::HasResources() const {
@@ -242,18 +267,18 @@ bool ConnectionInterfaceManager::HasResources() const {

void ConnectionInterfaceManager::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid,
                                                          ReadDataReadyCallback on_data_ready) {
  ASSERT(Exists(cid));
  ASSERT(ChannelExists(cid));
  return cid_to_interface_map_[cid]->SetReadDataReadyCallback(on_data_ready);
}

void ConnectionInterfaceManager::SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid,
                                                             ConnectionClosedCallback on_closed) {
  ASSERT(Exists(cid));
  ASSERT(ChannelExists(cid));
  return cid_to_interface_map_[cid]->SetConnectionClosedCallback(on_closed);
}

bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
  if (!Exists(cid)) {
  if (!ChannelExists(cid)) {
    return false;
  }
  cid_to_interface_map_[cid]->Write(std::move(packet));
@@ -262,18 +287,16 @@ bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::u

class PendingConnection {
 public:
  PendingConnection(ConnectionInterfaceManager* connection_interface_manager, l2cap::Psm psm, hci::Address address,
                    ConnectionOpenCallback on_open, std::promise<uint16_t> completed)
      : connection_interface_manager_(connection_interface_manager), psm_(psm), address_(address),
  PendingConnection(ConnectionInterfaceManager* connection_interface_manager, ConnectionInterfaceDescriptor cid,
                    l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
                    std::promise<uint16_t> completed)
      : connection_interface_manager_(connection_interface_manager), cid_(cid), psm_(psm), address_(address),
        on_open_(std::move(on_open)), completed_(std::move(completed)) {}

  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
    LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    completed_.set_value(cid);
    // Attempt to avoid async race condition with upper stack
    std::this_thread::yield();
    connection_interface_manager_->ConnectionOpened(std::move(on_open_), address_, psm_, cid);
    connection_interface_manager_->AddChannel(cid_, std::move(channel));
    connection_interface_manager_->ConnectionOpened(std::move(on_open_), address_, psm_, cid_);
  }

  void OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
@@ -295,11 +318,13 @@ class PendingConnection {
        break;
    }
    completed_.set_value(kInvalidConnectionInterfaceDescriptor);
    connection_interface_manager_->ConnectionFailed(address_, psm_);
    connection_interface_manager_->ConnectionFailed(std::move(on_open_), address_, psm_);
    connection_interface_manager_->FreeConnectionInterfaceDescriptor(cid_);
  }

 private:
  ConnectionInterfaceManager* connection_interface_manager_;
  const ConnectionInterfaceDescriptor cid_;
  const l2cap::Psm psm_;
  const hci::Address address_;
  ConnectionOpenCallback on_open_;
@@ -326,7 +351,8 @@ class ServiceInterface {
    LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
              psm_);
    hci::Address address = channel->GetDevice();
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AllocateConnectionInterfaceDescriptor();
    connection_interface_manager_->AddChannel(cid, std::move(channel));
    connection_interface_manager_->ConnectionOpened(on_open_, address, psm_, cid);
  }

@@ -414,13 +440,17 @@ void L2cap::impl::UnregisterService(l2cap::Psm psm) {

void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
                                   std::promise<uint16_t> completed) {
  LOG_DEBUG("Initiating classic connection to psm:%hd device:%s", psm, address.ToString().c_str());
  auto pending_connection = std::make_shared<PendingConnection>(&connection_interface_manager_, psm, address,
  ConnectionInterfaceDescriptor cid = connection_interface_manager_.AllocateConnectionInterfaceDescriptor();
  completed.set_value(cid);

  auto pending_connection = std::make_shared<PendingConnection>(&connection_interface_manager_, cid, psm, address,
                                                                std::move(on_open), std::move(completed));
  // TODO(cmanton) hash psm/address pair into unordered map for pending_connection
  // This is ok for now
  psm_to_pending_connection_map_[psm] = pending_connection;
  // TODO(cmanton): Add ERTM mode support by changing configuratio_option in ConnectChannel()
  //
  LOG_DEBUG("Initiating classic connection to psm:%hd device:%s cifd:%hu", psm, address.ToString().c_str(), cid);
  bool rc = dynamic_channel_manager_->ConnectChannel(
      address, l2cap::classic::DynamicChannelConfigurationOption(), psm,
      common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
+6 −22
Original line number Diff line number Diff line
@@ -56,8 +56,6 @@ uint16_t bluetooth::shim::L2CA_Register(uint16_t client_psm,
              __func__, client_psm, psm);
    return 0;
  }
  shim_l2cap.Classic().RegisterPsm(psm, callbacks);

  LOG_INFO(LOG_TAG, "%s classic client_psm:%hd psm:%hd", __func__, client_psm,
           psm);

@@ -74,39 +72,25 @@ void bluetooth::shim::L2CA_Deregister(uint16_t client_psm) {
  }
  uint16_t psm = shim_l2cap.ConvertClientToRealPsm(client_psm);

  if (!shim_l2cap.Classic().IsPsmRegistered(psm)) {
    LOG_ERROR(LOG_TAG,
              "%s Not previously registered classic client_psm:%hd psm:%hd",
              __func__, client_psm, psm);
    return;
  }
  shim_l2cap.Classic().UnregisterPsm(psm);
  shim_l2cap.UnregisterService(psm);
  shim_l2cap.RemoveClientPsm(psm);
}

uint16_t bluetooth::shim::L2CA_AllocatePSM(void) {
  uint16_t psm = shim_l2cap.GetNextDynamicClassicPsm();
  shim_l2cap.Classic().AllocatePsm(psm);
  return psm;
  return shim_l2cap.GetNextDynamicClassicPsm();
}

uint16_t bluetooth::shim::L2CA_AllocateLePSM(void) {
  uint16_t psm = shim_l2cap.GetNextDynamicLePsm();
  shim_l2cap.Le().AllocatePsm(psm);
  return psm;
  return shim_l2cap.GetNextDynamicLePsm();
}

void bluetooth::shim::L2CA_FreeLePSM(uint16_t psm) {
  if (!shim_l2cap.Le().IsPsmAllocated(psm)) {
    LOG_ERROR(LOG_TAG, "%s Not previously allocated le psm:%hd", __func__, psm);
    return;
  }
  if (!shim_l2cap.Le().IsPsmRegistered(psm)) {
    LOG_ERROR(LOG_TAG, "%s Must deregister psm before deallocation psm:%hd",
              __func__, psm);
    LOG_ERROR(LOG_TAG, "%s Not previously registered le psm:%hd", __func__,
              psm);
    return;
  }
  shim_l2cap.Le().DeallocatePsm(psm);
  shim_l2cap.Le().UnregisterPsm(psm);
}

/**
+43 −80
Original line number Diff line number Diff line
@@ -23,42 +23,40 @@
#include "osi/include/allocator.h"
#include "osi/include/log.h"

constexpr size_t kBtHdrSize = sizeof(BT_HDR);
constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
constexpr bool kDisconnectResponseRequired = false;
constexpr size_t kBtHdrSize = sizeof(BT_HDR);
constexpr uint16_t kConnectionFail = 1;
constexpr uint16_t kConnectionSuccess = 0;

bool bluetooth::legacy::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
  return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
}
constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
constexpr uint8_t kUnusedId = 0;
constexpr uint16_t kUnusedResult = 0;

bool bluetooth::legacy::shim::PsmData::IsPsmRegistered(uint16_t psm) const {
  return IsPsmAllocated(psm) && psm_to_callback_map_.at(psm) != nullptr;
  return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
}

void bluetooth::legacy::shim::PsmData::AllocatePsm(uint16_t psm) {
  RegisterPsm(psm, nullptr);
bool bluetooth::legacy::shim::PsmData::HasClient(uint16_t psm) const {
  return IsPsmRegistered(psm) && psm_to_callback_map_.at(psm) != nullptr;
}

void bluetooth::legacy::shim::PsmData::RegisterPsm(
    uint16_t psm, const tL2CAP_APPL_INFO* callbacks) {
  CHECK(!HasClient(psm));
  psm_to_callback_map_[psm] = callbacks;
}

void bluetooth::legacy::shim::PsmData::UnregisterPsm(uint16_t psm) {
  psm_to_callback_map_[psm] = nullptr;
void bluetooth::legacy::shim::PsmData::RegisterPsm(uint16_t psm) {
  RegisterPsm(psm, nullptr);
}

void bluetooth::legacy::shim::PsmData::DeallocatePsm(uint16_t psm) {
void bluetooth::legacy::shim::PsmData::UnregisterPsm(uint16_t psm) {
  CHECK(IsPsmRegistered(psm));
  psm_to_callback_map_.erase(psm);
}

const tL2CAP_APPL_INFO* bluetooth::legacy::shim::PsmData::Callbacks(
    uint16_t psm) {
  if (psm_to_callback_map_.find(psm) == psm_to_callback_map_.end()) {
    LOG_WARN(LOG_TAG, "Accessing unknown psm:%hd:", psm);
    return nullptr;
  }
  CHECK(HasClient(psm));
  return psm_to_callback_map_[psm];
}

@@ -108,7 +106,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
    return real_psm;
  }

  while (Classic().IsPsmAllocated(classic_virtual_psm_)) {
  while (Classic().IsPsmRegistered(classic_virtual_psm_)) {
    classic_virtual_psm_ += 2;
    if (classic_virtual_psm_ >= kFinalClassicVirtualPsm) {
      classic_virtual_psm_ = kInitialClassicVirtualPsm;
@@ -118,7 +116,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
}

uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
  while (Le().IsPsmAllocated(le_dynamic_psm_)) {
  while (Le().IsPsmRegistered(le_dynamic_psm_)) {
    le_dynamic_psm_++;
    if (le_dynamic_psm_ > kFinalLeDynamicPsm) {
      le_dynamic_psm_ = kInitialLeDynamicPsm;
@@ -128,7 +126,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
}

uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicClassicPsm() {
  while (Classic().IsPsmAllocated(classic_dynamic_psm_)) {
  while (Classic().IsPsmRegistered(classic_dynamic_psm_)) {
    classic_dynamic_psm_ += 2;
    if (classic_dynamic_psm_ > kFinalClassicDynamicPsm) {
      classic_dynamic_psm_ = kInitialClassicDynamicPsm;
@@ -154,7 +152,6 @@ void bluetooth::legacy::shim::L2cap::RegisterService(
  if (!enable_snoop) {
    LOG_WARN(LOG_TAG, "UNIMPLEMENTED Cannot disable snooping on psm:%d", psm);
  }

  Classic().RegisterPsm(psm, callbacks);

  std::promise<void> register_completed;
@@ -188,11 +185,9 @@ void bluetooth::legacy::shim::L2cap::OnRemoteInitiatedConnectionCreated(

  CHECK(!ConnectionExists(cid));
  cid_to_psm_map_[cid] = psm;
  SetCallbacks(cid, Classic().Callbacks(psm));
  const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
  CHECK(callbacks != nullptr);
  callbacks->pL2CA_ConnectInd_Cb(raw_address, cid, psm /* UNUSED */,
                                 0 /* UNUSED */);
  SetDownstreamCallbacks(cid);
  Classic().Callbacks(psm)->pL2CA_ConnectInd_Cb(raw_address, cid, psm,
                                                kUnusedId);
}

void bluetooth::legacy::shim::L2cap::UnregisterService(uint16_t psm) {
@@ -205,7 +200,6 @@ void bluetooth::legacy::shim::L2cap::UnregisterService(uint16_t psm) {
  // TODO(cmanton) Check for open channels before unregistering
  bluetooth::shim::GetL2cap()->UnregisterService(psm);
  Classic().UnregisterPsm(psm);
  Classic().DeallocatePsm(psm);
}

uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
@@ -241,8 +235,8 @@ uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
              " connection_interface_descriptor:%hd",
              psm, raw_address.ToString().c_str(), cid);
    CHECK(!ConnectionExists(cid));
    cid_to_callback_map_[cid] = Classic().Callbacks(psm);
    cid_to_psm_map_[cid] = psm;
    SetCallbacks(cid, Classic().Callbacks(psm));
  }
  return cid;
}
@@ -253,11 +247,13 @@ void bluetooth::legacy::shim::L2cap::OnLocalInitiatedConnectionCreated(
            "Sending connection confirm to the upper stack but really "
            "a connection to %s has already been done cid:%hd",
            string_address.c_str(), cid);
  // TODO(cmanton) Make sure the device is correct for locally initiated
  const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
  CHECK(callbacks != nullptr);
  callbacks->pL2CA_ConnectCfm_Cb(cid, kConnectionSuccess);
};
  uint16_t status = kConnectionFail;
  if (cid != kInvalidConnectionInterfaceDescriptor) {
    SetDownstreamCallbacks(cid);
    status = kConnectionSuccess;
  }
  Classic().Callbacks(psm)->pL2CA_ConnectCfm_Cb(cid, status);
}

bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
@@ -271,40 +267,7 @@ bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
  return true;
}

bool bluetooth::legacy::shim::L2cap::WriteFlushable(uint16_t cid,
                                                    BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
  size_t len = bt_hdr->len;
  if (!ConnectionExists(cid) || len == 0) {
    return false;
  }
  bluetooth::shim::GetL2cap()->WriteFlushable(cid, data, len);
  return true;
}

bool bluetooth::legacy::shim::L2cap::WriteNonFlushable(uint16_t cid,
                                                       BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
  size_t len = bt_hdr->len;
  if (!ConnectionExists(cid) || len == 0) {
    return false;
  }
  bluetooth::shim::GetL2cap()->WriteNonFlushable(cid, data, len);
  return true;
}

bool bluetooth::legacy::shim::L2cap::SetCallbacks(
    uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
  CHECK(callbacks != nullptr);
  CHECK(ConnectionExists(cid));
  LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
      << "Already have callbacks registered for "
         "connection_interface_descriptor:"
      << cid;
  cid_to_callback_map_[cid] = callbacks;

void bluetooth::legacy::shim::L2cap::SetDownstreamCallbacks(uint16_t cid) {
  bluetooth::shim::GetL2cap()->SetReadDataReadyCallback(
      cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
        LOG_DEBUG(LOG_TAG, "OnDataReady cid:%hd len:%zd", cid, data.size());
@@ -319,20 +282,23 @@ bool bluetooth::legacy::shim::L2cap::SetCallbacks(
  bluetooth::shim::GetL2cap()->SetConnectionClosedCallback(
      cid, [this](uint16_t cid, int error_code) {
        LOG_DEBUG(LOG_TAG, "OnChannel closed callback cid:%hd", cid);
        if (cid_to_callback_map_.find(cid) != cid_to_callback_map_.end()) {
          cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(
              cid, kDisconnectResponseRequired);
          cid_to_callback_map_.erase(cid);
        } else if (cid_closing_set_.count(cid) == 1) {
          cid_closing_set_.erase(cid);
        } else {
        if (cid_to_callback_map_.find(cid) == cid_to_callback_map_.end()) {
          LOG_WARN(LOG_TAG, "%s Unexpected channel closure cid:%hd", __func__,
                   cid);
          return;
        }
        CHECK(cid_to_psm_map_.find(cid) != cid_to_psm_map_.end());
        cid_to_psm_map_.erase(cid);

        if (cid_closing_set_.count(cid) == 1) {
          cid_closing_set_.erase(cid);
          cid_to_callback_map_[cid]->pL2CA_DisconnectCfm_Cb(cid, kUnusedResult);
        } else {
          cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(
              cid, kDisconnectResponseRequired);
        }
        cid_to_callback_map_.erase(cid);
      });
  return true;
}

bool bluetooth::legacy::shim::L2cap::ConnectResponse(
@@ -353,8 +319,6 @@ bool bluetooth::legacy::shim::L2cap::ConfigRequest(

  bluetooth::shim::GetL2cap()->SendLoopbackResponse([this, cid]() {
    CHECK(ConnectionExists(cid));
    const tL2CAP_APPL_INFO* callbacks = cid_to_callback_map_[cid];
    CHECK(callbacks != nullptr);
    tL2CAP_CFG_INFO cfg_info{
        .result = L2CAP_CFG_OK,
        .mtu_present = false,
@@ -365,8 +329,8 @@ bool bluetooth::legacy::shim::L2cap::ConfigRequest(
        .ext_flow_spec_present = false,
        .flags = 0,
    };
    callbacks->pL2CA_ConfigCfm_Cb(cid, &cfg_info);
    callbacks->pL2CA_ConfigInd_Cb(cid, &cfg_info);
    cid_to_callback_map_[cid]->pL2CA_ConfigCfm_Cb(cid, &cfg_info);
    cid_to_callback_map_[cid]->pL2CA_ConfigInd_Cb(cid, &cfg_info);
  });
  return true;
}
@@ -384,9 +348,8 @@ bool bluetooth::legacy::shim::L2cap::ConfigResponse(
bool bluetooth::legacy::shim::L2cap::DisconnectRequest(uint16_t cid) {
  CHECK(ConnectionExists(cid));
  LOG_DEBUG(LOG_TAG, "%s cid:%hu", __func__, cid);
  bluetooth::shim::GetL2cap()->CloseConnection(cid);
  cid_to_callback_map_.erase(cid);
  cid_closing_set_.insert(cid);
  bluetooth::shim::GetL2cap()->CloseConnection(cid);
  return true;
}

+14 −10
Original line number Diff line number Diff line
@@ -33,19 +33,25 @@ static constexpr uint16_t kFinalClassicVirtualPsm = 0x8000;
static constexpr uint16_t kInitialLeDynamicPsm = 0x0080;
static constexpr uint16_t kFinalLeDynamicPsm = 0x00ff;

using PsmData = struct {
  bool IsPsmAllocated(uint16_t psm) const;
struct PsmData {
  bool IsPsmRegistered(uint16_t psm) const;

  void AllocatePsm(uint16_t psm);
  bool HasClient(uint16_t psm) const;
  void RegisterPsm(uint16_t psm, const tL2CAP_APPL_INFO* callbacks);

  void RegisterPsm(uint16_t psm);
  void UnregisterPsm(uint16_t psm);
  void DeallocatePsm(uint16_t psm);

  const tL2CAP_APPL_INFO* Callbacks(uint16_t psm);

 private:
  /**
   * Mapping of psm to client callback.
   *
   * The current API allows a client may reserve a psm but not
   * provide a callback which is reflected in a mapping of a
   * valid psm key entry but a nullptr value.
   *
   * A valid client is indicated with a valid psm key entry and a
   * non-nullptr value.
   */
  std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> psm_to_callback_map_;
};

@@ -58,8 +64,6 @@ class L2cap {
  uint16_t CreateConnection(uint16_t psm, const RawAddress& raw_address);

  bool Write(uint16_t cid, BT_HDR* bt_hdr);
  bool WriteFlushable(uint16_t cid, BT_HDR* bt_hdr);
  bool WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr);

  void OnLocalInitiatedConnectionCreated(std::string string_address,
                                         uint16_t psm, uint16_t cid);
@@ -90,7 +94,7 @@ class L2cap {

 private:
  uint16_t GetNextVirtualPsm(uint16_t real_psm);
  bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* callbacks);
  void SetDownstreamCallbacks(uint16_t cid);

  PsmData classic_;
  PsmData le_;