L2cap shim layer with legacy
Bug: 141758481
Test: compiles and gracefully fails connect operation
Change-Id: Id0cdc9f0cd8efed18f9a3b6df24207726f0bbd3a
diff --git a/system/main/shim/entry.cc b/system/main/shim/entry.cc
index a460de6..8768818 100644
--- a/system/main/shim/entry.cc
+++ b/system/main/shim/entry.cc
@@ -50,6 +50,10 @@
return GetGabeldorscheStack()->GetHciLayer();
}
+bluetooth::shim::IL2cap* bluetooth::shim::GetL2cap() {
+ return GetGabeldorscheStack()->GetL2cap();
+}
+
bluetooth::shim::IPage* bluetooth::shim::GetPage() {
return GetGabeldorscheStack()->GetPage();
}
diff --git a/system/main/shim/entry.h b/system/main/shim/entry.h
index fd8ef0e..a4d4cf4 100644
--- a/system/main/shim/entry.h
+++ b/system/main/shim/entry.h
@@ -43,6 +43,7 @@
bluetooth::shim::IConnectability* GetConnectability();
bluetooth::shim::IInquiry* GetInquiry();
bluetooth::shim::IHciLayer* GetHciLayer();
+bluetooth::shim::IL2cap* GetL2cap();
bluetooth::shim::IPage* GetPage();
} // namespace shim
diff --git a/system/main/shim/l2c_api.cc b/system/main/shim/l2c_api.cc
index 4ba961b..5b6c49c 100644
--- a/system/main/shim/l2c_api.cc
+++ b/system/main/shim/l2c_api.cc
@@ -23,18 +23,21 @@
static bluetooth::shim::L2cap shim_l2cap;
+/**
+ * Classic Service Registration APIs
+ */
uint16_t bluetooth::shim::L2CA_Register(uint16_t client_psm,
- tL2CAP_APPL_INFO* p_cb_info,
+ tL2CAP_APPL_INFO* callbacks,
bool enable_snoop) {
if (L2C_INVALID_PSM(client_psm)) {
LOG_ERROR(LOG_TAG, "%s Invalid classic psm:0x%04x", __func__, client_psm);
return 0;
}
- if ((p_cb_info->pL2CA_ConfigCfm_Cb == nullptr) ||
- (p_cb_info->pL2CA_ConfigInd_Cb == nullptr) ||
- (p_cb_info->pL2CA_DataInd_Cb == nullptr) ||
- (p_cb_info->pL2CA_DisconnectInd_Cb == nullptr)) {
+ if ((callbacks->pL2CA_ConfigCfm_Cb == nullptr) ||
+ (callbacks->pL2CA_ConfigInd_Cb == nullptr) ||
+ (callbacks->pL2CA_DataInd_Cb == nullptr) ||
+ (callbacks->pL2CA_DisconnectInd_Cb == nullptr)) {
LOG_ERROR(LOG_TAG, "%s Invalid classic callbacks psm:0x%04x", __func__,
client_psm);
return 0;
@@ -43,7 +46,7 @@
/**
* Check if this is a registration for an outgoing-only connection.
*/
- bool is_outgoing_connection_only = p_cb_info->pL2CA_ConnectInd_Cb == nullptr;
+ bool is_outgoing_connection_only = callbacks->pL2CA_ConnectInd_Cb == nullptr;
uint16_t psm = shim_l2cap.ConvertClientToRealPsm(client_psm,
is_outgoing_connection_only);
@@ -53,13 +56,13 @@
__func__, client_psm, psm);
return 0;
}
- shim_l2cap.Classic().RegisterPsm(psm, p_cb_info);
+ shim_l2cap.Classic().RegisterPsm(psm, callbacks);
LOG_INFO(LOG_TAG, "%s classic client_psm:0x%04x psm:0x%04x", __func__,
client_psm, psm);
- // TODO(cmanton) Register this service with GD
- // TODO(cmanton) Fake out a config negotiator
+ shim_l2cap.Register(psm, callbacks, enable_snoop);
+
return psm;
}
@@ -107,62 +110,20 @@
shim_l2cap.Le().DeallocatePsm(psm);
}
+/**
+ * Classic Connection Oriented Channel APIS
+ */
uint16_t bluetooth::shim::L2CA_ErtmConnectReq(uint16_t psm,
- const RawAddress& p_bd_addr,
+ const RawAddress& raw_address,
tL2CAP_ERTM_INFO* p_ertm_info) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_ertm_info:%p", __func__,
- psm, p_bd_addr.ToString().c_str(), p_ertm_info);
- return 0;
+ CHECK(p_ertm_info == nullptr)
+ << "UNIMPLEMENTED set enhanced retransmission mode config";
+ return shim_l2cap.Connect(psm, raw_address);
}
uint16_t bluetooth::shim::L2CA_ConnectReq(uint16_t psm,
- const RawAddress& p_bd_addr) {
- return bluetooth::shim::L2CA_ErtmConnectReq(psm, p_bd_addr, nullptr);
-}
-
-uint16_t bluetooth::shim::L2CA_RegisterLECoc(uint16_t psm,
- tL2CAP_APPL_INFO* p_cb_info) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd p_cb_info:%p", __func__, psm,
- p_cb_info);
- return 0;
-}
-
-void bluetooth::shim::L2CA_DeregisterLECoc(uint16_t psm) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd", __func__, psm);
-}
-
-uint16_t bluetooth::shim::L2CA_ConnectLECocReq(uint16_t psm,
- const RawAddress& p_bd_addr,
- tL2CAP_LE_CFG_INFO* p_cfg) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_cfg:%p", __func__, psm,
- p_bd_addr.ToString().c_str(), p_cfg);
- return 0;
-}
-
-bool bluetooth::shim::L2CA_ConnectLECocRsp(const RawAddress& p_bd_addr,
- uint8_t id, uint16_t lcid,
- uint16_t result, uint16_t status,
- tL2CAP_LE_CFG_INFO* p_cfg) {
- LOG_INFO(LOG_TAG,
- "UNIMPLEMENTED %s addr:%s id:%hhd lcid:%hd result:%hd status:%hd "
- "p_cfg:%p",
- __func__, p_bd_addr.ToString().c_str(), id, lcid, result, status,
- p_cfg);
- return false;
-}
-
-bool bluetooth::shim::L2CA_GetPeerLECocConfig(uint16_t lcid,
- tL2CAP_LE_CFG_INFO* peer_cfg) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd peer_cfg:%p", __func__, lcid,
- peer_cfg);
- return false;
-}
-
-bool bluetooth::shim::L2CA_SetConnectionCallbacks(
- uint16_t local_cid, const tL2CAP_APPL_INFO* callbacks) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd callbacks:%p", __func__,
- local_cid, callbacks);
- return false;
+ const RawAddress& raw_address) {
+ return bluetooth::shim::L2CA_ErtmConnectReq(psm, raw_address, nullptr);
}
bool bluetooth::shim::L2CA_ErtmConnectRsp(const RawAddress& p_bd_addr,
@@ -204,6 +165,92 @@
return false;
}
+/**
+ * Le Connection Oriented Channel APIs
+ */
+uint16_t bluetooth::shim::L2CA_RegisterLECoc(uint16_t psm,
+ tL2CAP_APPL_INFO* callbacks) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd callbacks:%p", __func__, psm,
+ callbacks);
+ return 0;
+}
+
+void bluetooth::shim::L2CA_DeregisterLECoc(uint16_t psm) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd", __func__, psm);
+}
+
+uint16_t bluetooth::shim::L2CA_ConnectLECocReq(uint16_t psm,
+ const RawAddress& p_bd_addr,
+ tL2CAP_LE_CFG_INFO* p_cfg) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_cfg:%p", __func__, psm,
+ p_bd_addr.ToString().c_str(), p_cfg);
+ return 0;
+}
+
+bool bluetooth::shim::L2CA_ConnectLECocRsp(const RawAddress& p_bd_addr,
+ uint8_t id, uint16_t lcid,
+ uint16_t result, uint16_t status,
+ tL2CAP_LE_CFG_INFO* p_cfg) {
+ LOG_INFO(LOG_TAG,
+ "UNIMPLEMENTED %s addr:%s id:%hhd lcid:%hd result:%hd status:%hd "
+ "p_cfg:%p",
+ __func__, p_bd_addr.ToString().c_str(), id, lcid, result, status,
+ p_cfg);
+ return false;
+}
+
+bool bluetooth::shim::L2CA_GetPeerLECocConfig(uint16_t lcid,
+ tL2CAP_LE_CFG_INFO* peer_cfg) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd peer_cfg:%p", __func__, lcid,
+ peer_cfg);
+ return false;
+}
+
+/**
+ * Channel Data Writes
+ */
+bool bluetooth::shim::L2CA_SetConnectionCallbacks(
+ uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
+ return shim_l2cap.SetCallbacks(cid, callbacks);
+}
+
+uint8_t bluetooth::shim::L2CA_DataWriteEx(uint16_t cid, BT_HDR* bt_hdr,
+ uint16_t flags) {
+ if (shim_l2cap.IsCongested(cid)) {
+ return L2CAP_DW_CONGESTED;
+ }
+
+ bool write_success = false;
+ switch (flags) {
+ case L2CAP_FLUSHABLE_CH_BASED:
+ write_success = shim_l2cap.Write(cid, bt_hdr);
+ break;
+ case L2CAP_FLUSHABLE_PKT:
+ write_success = shim_l2cap.WriteFlushable(cid, bt_hdr);
+ break;
+ case L2CAP_NON_FLUSHABLE_PKT:
+ write_success = shim_l2cap.WriteNonFlushable(cid, bt_hdr);
+ break;
+ }
+ return write_success ? L2CAP_DW_SUCCESS : L2CAP_DW_FAILED;
+}
+
+uint8_t bluetooth::shim::L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
+ return bluetooth::shim::L2CA_DataWriteEx(cid, p_data,
+ L2CAP_FLUSHABLE_CH_BASED);
+}
+
+/**
+ * L2cap Layer APIs
+ */
+uint8_t bluetooth::shim::L2CA_SetDesireRole(uint8_t new_role) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return 0;
+}
+
+/**
+ * Ping APIs
+ */
bool bluetooth::shim::L2CA_Ping(const RawAddress& p_bd_addr,
tL2CA_ECHO_RSP_CB* p_callback) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s addr:%s p_callback:%p", __func__,
@@ -218,18 +265,9 @@
return false;
}
-bool bluetooth::shim::L2CA_GetIdentifiers(uint16_t lcid, uint16_t* rcid,
- uint16_t* handle) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
-bool bluetooth::shim::L2CA_SetIdleTimeout(uint16_t cid, uint16_t timeout,
- bool is_global) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
+/**
+ * Link APIs
+ */
bool bluetooth::shim::L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr,
uint16_t timeout,
tBT_TRANSPORT transport) {
@@ -237,11 +275,6 @@
return false;
}
-uint8_t bluetooth::shim::L2CA_SetDesireRole(uint8_t new_role) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return 0;
-}
-
uint16_t bluetooth::shim::L2CA_LocalLoopbackReq(uint16_t psm, uint16_t handle,
const RawAddress& p_bd_addr) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -254,30 +287,6 @@
return false;
}
-bool bluetooth::shim::L2CA_FlowControl(uint16_t cid, bool data_enabled) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
-bool bluetooth::shim::L2CA_SendTestSFrame(uint16_t cid, uint8_t sup_type,
- uint8_t back_track) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
-bool bluetooth::shim::L2CA_SetTxPriority(uint16_t cid,
- tL2CAP_CHNL_PRIORITY priority) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
-bool bluetooth::shim::L2CA_SetChnlDataRate(uint16_t cid,
- tL2CAP_CHNL_DATA_RATE tx,
- tL2CAP_CHNL_DATA_RATE rx) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
bool bluetooth::shim::L2CA_SetFlushTimeout(const RawAddress& bd_addr,
uint16_t flush_tout) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -297,11 +306,9 @@
return false;
}
-uint8_t bluetooth::shim::L2CA_GetChnlFcrMode(uint16_t lcid) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return 0;
-}
-
+/**
+ * Fixed Channel APIs
+ */
bool bluetooth::shim::L2CA_RegisterFixedChannel(uint16_t fixed_cid,
tL2CAP_FIXED_CHNL_REG* p_freg) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -334,13 +341,9 @@
return false;
}
-bool bluetooth::shim::L2CA_SetFixedChannelTout(const RawAddress& rem_bda,
- uint16_t fixed_cid,
- uint16_t idle_tout) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
+/**
+ * Channel Configuration API
+ */
bool bluetooth::shim::L2CA_GetCurrentConfig(
uint16_t lcid, tL2CAP_CFG_INFO** pp_our_cfg,
tL2CAP_CH_CFG_BITS* p_our_cfg_bits, tL2CAP_CFG_INFO** pp_peer_cfg,
@@ -356,31 +359,74 @@
return false;
}
-bool bluetooth::shim::L2CA_RegForNoCPEvt(tL2CA_NOCP_CB* p_cb,
- const RawAddress& p_bda) {
+/**
+ * Channel hygiene APIs
+ */
+bool bluetooth::shim::L2CA_GetIdentifiers(uint16_t lcid, uint16_t* rcid,
+ uint16_t* handle) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
return false;
}
-uint8_t bluetooth::shim::L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
+bool bluetooth::shim::L2CA_SetIdleTimeout(uint16_t cid, uint16_t timeout,
+ bool is_global) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
+bool bluetooth::shim::L2CA_FlowControl(uint16_t cid, bool data_enabled) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
+bool bluetooth::shim::L2CA_SendTestSFrame(uint16_t cid, uint8_t sup_type,
+ uint8_t back_track) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
+bool bluetooth::shim::L2CA_SetTxPriority(uint16_t cid,
+ tL2CAP_CHNL_PRIORITY priority) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
+bool bluetooth::shim::L2CA_SetChnlDataRate(uint16_t cid,
+ tL2CAP_CHNL_DATA_RATE tx,
+ tL2CAP_CHNL_DATA_RATE rx) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
+uint8_t bluetooth::shim::L2CA_GetChnlFcrMode(uint16_t lcid) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
return 0;
}
+bool bluetooth::shim::L2CA_SetFixedChannelTout(const RawAddress& rem_bda,
+ uint16_t fixed_cid,
+ uint16_t idle_tout) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
+
bool bluetooth::shim::L2CA_SetChnlFlushability(uint16_t cid,
bool is_flushable) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
return false;
}
-uint8_t bluetooth::shim::L2CA_DataWriteEx(uint16_t cid, BT_HDR* p_data,
- uint16_t flags) {
- LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
- return false;
-}
-
uint16_t bluetooth::shim::L2CA_FlushChannel(uint16_t lcid,
uint16_t num_to_flush) {
LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
return 0;
}
+
+/**
+ * Misc APIs
+ */
+bool bluetooth::shim::L2CA_RegForNoCPEvt(tL2CA_NOCP_CB* p_cb,
+ const RawAddress& p_bda) {
+ LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+ return false;
+}
diff --git a/system/main/shim/l2cap.cc b/system/main/shim/l2cap.cc
index 5afbb01..765ba0d 100644
--- a/system/main/shim/l2cap.cc
+++ b/system/main/shim/l2cap.cc
@@ -13,8 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "bt_shim_l2cap"
#include "main/shim/l2cap.h"
+#include "main/shim/entry.h"
+#include "main/shim/shim.h"
+#include "osi/include/allocator.h"
+#include "osi/include/log.h"
+
+constexpr size_t kBtHdrSize = sizeof(BT_HDR);
bool bluetooth::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
return psm_to_callback_map.find(psm) != psm_to_callback_map.end();
@@ -115,3 +122,92 @@
}
return classic_dynamic_psm_;
}
+
+void bluetooth::shim::L2cap::Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop) {
+ LOG_DEBUG(LOG_TAG, "Registering service psm:%hd", psm);
+
+ std::chrono::system_clock::time_point two_seconds =
+ std::chrono::system_clock::now() + std::chrono::seconds(2);
+
+ std::promise<void> register_completed;
+ auto completed = register_completed.get_future();
+ bluetooth::shim::GetL2cap()->RegisterService(psm, enable_snoop,
+ std::move(register_completed));
+ completed.wait();
+ if (std::future_status::ready != completed.wait_until(two_seconds)) {
+ LOG_WARN(LOG_TAG, "Timed out registering service to psm:%hd", psm);
+ }
+}
+
+uint16_t bluetooth::shim::L2cap::Connect(uint16_t psm,
+ const RawAddress& raw_address) {
+ LOG_DEBUG(LOG_TAG, "Requesting connection to psm:%hd address:%s", psm,
+ raw_address.ToString().c_str());
+
+ std::chrono::system_clock::time_point two_seconds =
+ std::chrono::system_clock::now() + std::chrono::seconds(2);
+
+ std::promise<uint16_t> connect_completed;
+ auto completed = connect_completed.get_future();
+ bluetooth::shim::GetL2cap()->Connect(psm, raw_address.ToString(),
+ std::move(connect_completed));
+ if (std::future_status::ready == completed.wait_until(two_seconds)) {
+ return completed.get();
+ }
+ LOG_WARN(LOG_TAG, "Timed out connecting to psm:%hd address:%s", psm,
+ raw_address.ToString().c_str());
+ return 0;
+}
+
+bool bluetooth::shim::L2cap::IsCongested(uint16_t cid) const {
+ LOG_WARN(LOG_TAG, "UNIMPLEMENTED checking congestion on a channel");
+ return false;
+}
+
+bool bluetooth::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
+ const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+ size_t len = bt_hdr->len;
+ return bluetooth::shim::GetL2cap()->Write(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::WriteFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+ const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+ size_t len = bt_hdr->len;
+ return bluetooth::shim::GetL2cap()->WriteFlushable(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+ const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+ size_t len = bt_hdr->len;
+ return bluetooth::shim::GetL2cap()->WriteNonFlushable(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::SetCallbacks(uint16_t cid,
+ const tL2CAP_APPL_INFO* callbacks) {
+ LOG_ASSERT(cid_to_callback_map_.find(cid) != cid_to_callback_map_.end())
+ << "Registering multiple channel callbacks cid:" << cid;
+ cid_to_callback_map_[cid] = callbacks;
+ bluetooth::shim::GetL2cap()->SetOnReadDataReady(
+ cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
+ LOG_INFO(LOG_TAG, "Got data on 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();
+
+ cid_to_callback_map_[cid]->pL2CA_DataInd_Cb(cid, bt_hdr);
+ });
+ bluetooth::shim::GetL2cap()->SetOnClose(cid, [this, &cid](int error_code) {
+ LOG_DEBUG(LOG_TAG, "Channel closed cid:%hd", cid);
+ cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(cid, true);
+ });
+ return true;
+}
+
+void bluetooth::shim::L2cap::ClearCallbacks(uint16_t cid) {
+ LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
+ << "Clearing callbacks that do not exist cid:" << cid;
+ cid_to_callback_map_.erase(cid);
+}
diff --git a/system/main/shim/l2cap.h b/system/main/shim/l2cap.h
index 4860dea..6653a4a 100644
--- a/system/main/shim/l2cap.h
+++ b/system/main/shim/l2cap.h
@@ -60,6 +60,17 @@
uint16_t ConvertClientToRealPsm(uint16_t psm);
void RemoveClientPsm(uint16_t client_psm);
+ void Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info, bool enable_snoop);
+ uint16_t Connect(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);
+ bool IsCongested(uint16_t cid) const;
+
+ bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* client_callbacks);
+ void ClearCallbacks(uint16_t cid);
+
private:
uint16_t GetNextVirtualPsm(uint16_t real_psm);
@@ -71,6 +82,7 @@
uint16_t classic_virtual_psm_;
std::unordered_map<uint16_t, uint16_t> client_psm_to_real_psm_map_;
+ std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> cid_to_callback_map_;
};
} // namespace shim