Loading system/gd/shim/l2cap.cc +50 −20 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <memory> #include <mutex> #include <queue> #include <set> #include <unordered_map> #include <vector> Loading Loading @@ -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); Loading @@ -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_++; } Loading @@ -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; Loading @@ -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 { Loading @@ -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)); Loading @@ -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) { Loading @@ -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_; Loading @@ -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); } Loading Loading @@ -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())), Loading system/main/shim/l2c_api.cc +6 −22 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } /** Loading system/main/shim/l2cap.cc +43 −80 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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( Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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()); Loading @@ -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( Loading @@ -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, Loading @@ -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; } Loading @@ -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; } Loading system/main/shim/l2cap.h +14 −10 Original line number Diff line number Diff line Loading @@ -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_; }; Loading @@ -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); Loading Loading @@ -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_; Loading Loading
system/gd/shim/l2cap.cc +50 −20 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <memory> #include <mutex> #include <queue> #include <set> #include <unordered_map> #include <vector> Loading Loading @@ -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); Loading @@ -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_++; } Loading @@ -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; Loading @@ -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 { Loading @@ -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)); Loading @@ -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) { Loading @@ -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_; Loading @@ -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); } Loading Loading @@ -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())), Loading
system/main/shim/l2c_api.cc +6 −22 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } /** Loading
system/main/shim/l2cap.cc +43 −80 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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( Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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()); Loading @@ -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( Loading @@ -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, Loading @@ -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; } Loading @@ -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; } Loading
system/main/shim/l2cap.h +14 −10 Original line number Diff line number Diff line Loading @@ -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_; }; Loading @@ -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); Loading Loading @@ -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_; Loading