+++ /dev/null
-/*
- * Copyright 2019 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.
- */
-#define LOG_TAG "bt_shim_l2cap"
-
-#include <cstdint>
-
-#include "main/shim/dumpsys.h"
-#include "main/shim/entry.h"
-#include "main/shim/l2cap.h"
-#include "main/shim/shim.h"
-#include "osi/include/allocator.h"
-#include "osi/include/log.h"
-#include "stack/include/btu.h"
-
-#include "shim/l2cap.h"
-
-namespace {
-constexpr char kModuleName[] = "shim::legacy::L2cap";
-constexpr bool kDisconnectResponseRequired = false;
-constexpr size_t kBtHdrSize = sizeof(BT_HDR);
-constexpr uint16_t kConnectionFail = 1;
-constexpr uint16_t kConnectionSuccess = 0;
-constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
-constexpr uint8_t kUnusedId = 0;
-} // namespace
-
-bool bluetooth::shim::legacy::PsmManager::IsPsmRegistered(uint16_t psm) const {
- return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
-}
-
-bool bluetooth::shim::legacy::PsmManager::HasClient(uint16_t psm) const {
- return IsPsmRegistered(psm) &&
- psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
-}
-
-void bluetooth::shim::legacy::PsmManager::RegisterPsm(
- uint16_t psm, const tL2CAP_APPL_INFO& callbacks) {
- CHECK(!HasClient(psm));
- psm_to_callback_map_.try_emplace(psm, tL2CAP_APPL_INFO(callbacks));
-}
-
-void bluetooth::shim::legacy::PsmManager::UnregisterPsm(uint16_t psm) {
- CHECK(IsPsmRegistered(psm));
- psm_to_callback_map_.erase(psm);
-}
-
-const tL2CAP_APPL_INFO bluetooth::shim::legacy::PsmManager::Callbacks(
- uint16_t psm) {
- CHECK(HasClient(psm));
- return psm_to_callback_map_[psm];
-}
-
-bluetooth::shim::legacy::L2cap::L2cap()
- : le_dynamic_psm_(kInitialLeDynamicPsm),
- classic_virtual_psm_(kInitialClassicVirtualPsm) {
- bluetooth::shim::RegisterDumpsysFunction(static_cast<void*>(this),
- [this](int fd) { Dump(fd); });
-}
-
-bluetooth::shim::legacy::L2cap::~L2cap() {
- bluetooth::shim::UnregisterDumpsysFunction(static_cast<void*>(this));
-}
-
-bluetooth::shim::legacy::PsmManager& bluetooth::shim::legacy::L2cap::Le() {
- return le_;
-}
-
-bluetooth::shim::legacy::PsmManager& bluetooth::shim::legacy::L2cap::Classic() {
- return classic_;
-}
-
-bool bluetooth::shim::legacy::L2cap::ConnectionExists(uint16_t cid) const {
- return cid_to_psm_map_.find(cid) != cid_to_psm_map_.end();
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::CidToPsm(uint16_t cid) const {
- CHECK(ConnectionExists(cid));
- return cid_to_psm_map_.at(cid);
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::ConvertClientToRealPsm(
- uint16_t client_psm, bool is_outgoing_only_connection) {
- if (!is_outgoing_only_connection) {
- return client_psm;
- }
- return GetNextVirtualPsm(client_psm);
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::ConvertClientToRealPsm(
- uint16_t client_psm) {
- if (client_psm_to_real_psm_map_.find(client_psm) ==
- client_psm_to_real_psm_map_.end()) {
- return client_psm;
- }
- return client_psm_to_real_psm_map_.at(client_psm);
-}
-
-void bluetooth::shim::legacy::L2cap::RemoveClientPsm(uint16_t client_psm) {
- if (client_psm_to_real_psm_map_.find(client_psm) !=
- client_psm_to_real_psm_map_.end()) {
- client_psm_to_real_psm_map_.erase(client_psm);
- }
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
- if (real_psm < kInitialClassicDynamicPsm) {
- return real_psm;
- }
-
- while (Classic().IsPsmRegistered(classic_virtual_psm_)) {
- classic_virtual_psm_ += 2;
- if (classic_virtual_psm_ >= kFinalClassicVirtualPsm) {
- classic_virtual_psm_ = kInitialClassicVirtualPsm;
- }
- }
- return classic_virtual_psm_;
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::GetNextDynamicLePsm() {
- while (Le().IsPsmRegistered(le_dynamic_psm_)) {
- le_dynamic_psm_++;
- if (le_dynamic_psm_ > kFinalLeDynamicPsm) {
- le_dynamic_psm_ = kInitialLeDynamicPsm;
- }
- }
- return le_dynamic_psm_;
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::RegisterService(
- uint16_t psm, const tL2CAP_APPL_INFO& callbacks, bool enable_snoop,
- tL2CAP_ERTM_INFO* p_ertm_info, uint16_t my_mtu,
- uint16_t required_remote_mtu) {
- if (Classic().IsPsmRegistered(psm)) {
- LOG_WARN("Service is already registered psm:%hd", psm);
- return 0;
- }
- if (!enable_snoop) {
- LOG_INFO("Disable snooping on psm basis unsupported psm:%d", psm);
- }
-
- LOG_INFO("Registering service on psm:%hd", psm);
- RegisterServicePromise register_promise;
- auto service_registered = register_promise.get_future();
- bool use_ertm = false;
- if (p_ertm_info != nullptr &&
- p_ertm_info->preferred_mode == L2CAP_FCR_ERTM_MODE) {
- use_ertm = true;
- }
- bluetooth::shim::GetL2cap()->RegisterClassicService(
- psm, use_ertm, my_mtu, required_remote_mtu,
- std::bind(
- &bluetooth::shim::legacy::L2cap::OnRemoteInitiatedConnectionCreated,
- this, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4),
- std::move(register_promise));
-
- uint16_t registered_psm = service_registered.get();
- if (registered_psm != psm) {
- LOG_WARN("Unable to register psm:%hd", psm);
- } else {
- LOG_INFO("Successfully registered psm:%hd", psm);
- Classic().RegisterPsm(registered_psm, callbacks);
- }
- return registered_psm;
-}
-
-void bluetooth::shim::legacy::L2cap::UnregisterService(uint16_t psm) {
- if (!Classic().IsPsmRegistered(psm)) {
- LOG_WARN("Service must be registered in order to unregister psm:%hd", psm);
- return;
- }
- for (auto& entry : cid_to_psm_map_) {
- if (entry.second == psm) {
- LOG_WARN(" Unregistering service with active channels psm:%hd cid:%hd",
- psm, entry.first);
- }
- }
-
- LOG_INFO("Unregistering service on psm:%hd", psm);
- UnregisterServicePromise unregister_promise;
- auto service_unregistered = unregister_promise.get_future();
- bluetooth::shim::GetL2cap()->UnregisterClassicService(
- psm, std::move(unregister_promise));
- service_unregistered.wait();
- Classic().UnregisterPsm(psm);
-}
-
-uint16_t bluetooth::shim::legacy::L2cap::CreateConnection(
- uint16_t psm, const RawAddress& raw_address) {
- if (!Classic().IsPsmRegistered(psm)) {
- LOG_WARN("Service must be registered in order to connect psm:%hd", psm);
- return kInvalidConnectionInterfaceDescriptor;
- }
-
- CreateConnectionPromise create_promise;
- auto created = create_promise.get_future();
- LOG_INFO("Initiating local connection to psm:%hd address:%s", psm,
- raw_address.ToString().c_str());
-
- bluetooth::shim::GetL2cap()->CreateClassicConnection(
- psm, raw_address.ToString(),
- std::bind(
- &bluetooth::shim::legacy::L2cap::OnLocalInitiatedConnectionCreated,
- this, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5),
- std::move(create_promise));
-
- uint16_t cid = created.get();
- if (cid == kInvalidConnectionInterfaceDescriptor) {
- LOG_WARN("Failed to initiate connection interface to psm:%hd address:%s",
- psm, raw_address.ToString().c_str());
- } else {
- LOG_INFO(
- "Successfully initiated connection to psm:%hd address:%s"
- " connection_interface_descriptor:%hd",
- psm, raw_address.ToString().c_str(), cid);
- CHECK(!ConnectionExists(cid));
- cid_to_psm_map_[cid] = psm;
- }
- return cid;
-}
-
-void bluetooth::shim::legacy::L2cap::OnLocalInitiatedConnectionCreated(
- std::string string_address, uint16_t psm, uint16_t cid, uint16_t remote_cid,
- bool connected) {
- cid_to_remote_cid_map_[cid] = remote_cid;
- if (cid_closing_set_.count(cid) == 0) {
- if (connected) {
- SetDownstreamCallbacks(cid);
- } else {
- LOG_WARN("Failed intitiating connection remote:%s psm:%hd cid:%hd",
- string_address.c_str(), psm, cid);
- }
- do_in_main_thread(
- FROM_HERE,
- base::Bind(classic_.Callbacks(psm).pL2CA_ConnectCfm_Cb, cid,
- connected ? (kConnectionSuccess) : (kConnectionFail)));
- tL2CAP_CFG_INFO cfg_info{};
- do_in_main_thread(
- FROM_HERE,
- base::Bind(classic_.Callbacks(CidToPsm(cid)).pL2CA_ConfigCfm_Cb, cid,
- L2CAP_INITIATOR_LOCAL, base::Unretained(&cfg_info)));
-
- } else {
- LOG_INFO("Connection Closed before presentation to upper layer");
- if (connected) {
- SetDownstreamCallbacks(cid);
- bluetooth::shim::GetL2cap()->CloseClassicConnection(cid);
- } else {
- LOG_INFO("Connection failed after initiator closed");
- }
- }
-}
-
-void bluetooth::shim::legacy::L2cap::OnRemoteInitiatedConnectionCreated(
- std::string string_address, uint16_t psm, uint16_t cid,
- uint16_t remote_cid) {
- RawAddress raw_address;
- RawAddress::FromString(string_address, raw_address);
-
- LOG_INFO(
- "Sending connection indicator to upper stack from device:%s "
- "psm:%hd cid:%hd",
- string_address.c_str(), psm, cid);
-
- CHECK(!ConnectionExists(cid));
- cid_to_psm_map_[cid] = psm;
- cid_to_remote_cid_map_[cid] = remote_cid;
- SetDownstreamCallbacks(cid);
- do_in_main_thread(
- FROM_HERE,
- base::Bind(classic_.Callbacks(CidToPsm(cid)).pL2CA_ConnectInd_Cb,
- raw_address, cid, psm, kUnusedId));
- tL2CAP_CFG_INFO cfg_info{};
- do_in_main_thread(
- FROM_HERE,
- base::Bind(classic_.Callbacks(CidToPsm(cid)).pL2CA_ConfigCfm_Cb, cid,
- L2CAP_INITIATOR_REMOTE, base::Unretained(&cfg_info)));
-}
-
-bool bluetooth::shim::legacy::L2cap::Write(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;
- }
- LOG_INFO("Writing data cid:%hd len:%zd", cid, len);
- bluetooth::shim::GetL2cap()->Write(cid, data, len);
- return true;
-}
-
-void bluetooth::shim::legacy::L2cap::SetDownstreamCallbacks(uint16_t cid) {
- bluetooth::shim::GetL2cap()->SetReadDataReadyCallback(
- cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
- LOG_INFO("OnDataReady cid:%hd len:%zd", cid, data.size());
- BT_HDR* bt_hdr =
- static_cast<BT_HDR*>(osi_calloc(data.size() + kBtHdrSize));
- std::copy(data.begin(), data.end(), bt_hdr->data);
- bt_hdr->len = data.size();
- do_in_main_thread(
- FROM_HERE,
- base::Bind(classic_.Callbacks(CidToPsm(cid)).pL2CA_DataInd_Cb, cid,
- base::Unretained(bt_hdr)));
- });
-
- bluetooth::shim::GetL2cap()->SetConnectionClosedCallback(
- cid, [this](uint16_t cid, int error_code) {
- LOG_INFO("OnChannel closed callback cid:%hd", cid);
- if (!ConnectionExists(cid)) {
- LOG_WARN("%s Unexpected channel closure cid:%hd", __func__, cid);
- return;
- }
- if (cid_closing_set_.count(cid) == 1) {
- cid_closing_set_.erase(cid);
- } else {
- do_in_main_thread(
- FROM_HERE,
- base::Bind(
- classic_.Callbacks(CidToPsm(cid)).pL2CA_DisconnectInd_Cb, cid,
- kDisconnectResponseRequired));
- }
- cid_to_psm_map_.erase(cid);
- cid_to_remote_cid_map_.erase(cid);
- });
-}
-
-bool bluetooth::shim::legacy::L2cap::DisconnectRequest(uint16_t cid) {
- CHECK(ConnectionExists(cid));
- if (cid_closing_set_.find(cid) != cid_closing_set_.end()) {
- LOG_WARN("%s Channel already in closing state cid:%hu", __func__, cid);
- return false;
- }
- LOG_INFO("%s initiated locally cid:%hu", __func__, cid);
- cid_closing_set_.insert(cid);
- bluetooth::shim::GetL2cap()->CloseClassicConnection(cid);
- return true;
-}
-
-void bluetooth::shim::legacy::L2cap::Dump(int fd) {
- if (cid_to_psm_map_.empty()) {
- dprintf(fd, "%s No active l2cap channels\n", kModuleName);
- } else {
- for (auto& connection : cid_to_psm_map_) {
- dprintf(fd, "%s active l2cap channel cid:%hd psm:%hd\n", kModuleName,
- connection.first, connection.second);
- }
- }
-}
-
-bool bluetooth::shim::legacy::L2cap::GetRemoteCid(uint16_t cid,
- uint16_t* remote_cid) {
- auto it = cid_to_remote_cid_map_.find(cid);
- if (it == cid_to_remote_cid_map_.end()) {
- return false;
- }
-
- *remote_cid = it->second;
- return true;
-}
+++ /dev/null
-/*
- * Copyright 2019 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 <set>
-#include <unordered_map>
-
-#include "main/shim/dumpsys.h"
-#include "stack/include/l2c_api.h"
-
-namespace bluetooth {
-namespace shim {
-namespace legacy {
-
-static constexpr uint16_t kInitialClassicDynamicPsm = 0x1001;
-static constexpr uint16_t kFinalClassicDynamicPsm = 0xfeff;
-static constexpr uint16_t kInitialClassicVirtualPsm = kInitialClassicDynamicPsm;
-static constexpr uint16_t kFinalClassicVirtualPsm = 0x8000;
-static constexpr uint16_t kInitialLeDynamicPsm = 0x0080;
-static constexpr uint16_t kFinalLeDynamicPsm = 0x00ff;
-
-class PsmManager {
- public:
- bool IsPsmRegistered(uint16_t psm) const;
- bool HasClient(uint16_t psm) const;
- void RegisterPsm(uint16_t psm, const tL2CAP_APPL_INFO& callbacks);
- void UnregisterPsm(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_;
-};
-
-class L2cap {
- public:
- uint16_t RegisterService(uint16_t psm, const tL2CAP_APPL_INFO& callbacks,
- bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info,
- uint16_t my_mtu, uint16_t required_remote_mtu);
- void UnregisterService(uint16_t psm);
-
- uint16_t CreateConnection(uint16_t psm, const RawAddress& raw_address);
-
- bool Write(uint16_t cid, BT_HDR* bt_hdr);
-
- void OnLocalInitiatedConnectionCreated(std::string string_address,
- uint16_t psm, uint16_t cid,
- uint16_t remote_cid, bool connected);
- void OnRemoteInitiatedConnectionCreated(std::string string_addresss,
- uint16_t psm, uint16_t cid,
- uint16_t remote_cid);
-
- uint16_t GetNextDynamicLePsm();
-
- uint16_t ConvertClientToRealPsm(uint16_t psm,
- bool is_outgoing_only_connection);
- uint16_t ConvertClientToRealPsm(uint16_t psm);
- void RemoveClientPsm(uint16_t client_psm);
-
- bool DisconnectRequest(uint16_t cid);
-
- bool GetRemoteCid(uint16_t cid, uint16_t* remote_cid);
-
- L2cap();
- ~L2cap();
-
- PsmManager& Classic();
- PsmManager& Le();
-
- private:
- uint16_t GetNextVirtualPsm(uint16_t real_psm);
- void SetDownstreamCallbacks(uint16_t cid);
-
- void Dump(int fd);
-
- PsmManager classic_;
- PsmManager le_;
-
- bool ConnectionExists(uint16_t cid) const;
- uint16_t CidToPsm(uint16_t cid) const;
-
- uint16_t le_dynamic_psm_;
- uint16_t classic_virtual_psm_;
-
- std::unordered_map<uint16_t,
- std::function<void(std::function<void(uint16_t c)>)>>
- cid_to_postable_map_;
- std::set<uint16_t> cid_closing_set_;
-
- std::unordered_map<uint16_t, uint16_t> cid_to_psm_map_;
- std::unordered_map<uint16_t, uint16_t> cid_to_remote_cid_map_;
- std::unordered_map<uint16_t, uint16_t> client_psm_to_real_psm_map_;
-};
-
-} // namespace legacy
-} // namespace shim
-} // namespace bluetooth