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

Commit fe4ceae0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Synchronize l2cap channel for client apps"

parents e7786ffa 5d8e3894
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_;