summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Liang Li <lianglli@google.com> 2024-12-09 01:11:34 -0800
committer Liang Li <lianglli@google.com> 2024-12-12 19:12:32 -0800
commitc9f93cdf363fa32d0536b0119d60525211314444 (patch)
tree9cf1eb57565cb0ecf4d3127094a782a0120f3877
parentcfae36f86663b10eca17b72deb7896cf860656ee (diff)
Add helper functions to get RFCOMM channel and L2CAP local mtu information
Flag: com.android.bluetooth.flags.socket_settings_api Bug: 342012881 Bug: 374358112 Test: m -j Change-Id: Id94712de7fb1ebdd88dd850db16e176092c10185
-rw-r--r--system/stack/include/l2cap_interface.h17
-rw-r--r--system/stack/include/port_api.h26
-rw-r--r--system/stack/l2cap/internal/l2c_api.h17
-rw-r--r--system/stack/l2cap/l2c_api.cc27
-rw-r--r--system/stack/l2cap/l2c_api.h2
-rw-r--r--system/stack/l2cap/l2cap_api.cc5
-rw-r--r--system/stack/rfcomm/port_api.cc48
-rw-r--r--system/test/mock/mock_stack_l2cap_api.cc5
-rw-r--r--system/test/mock/mock_stack_l2cap_api.h10
-rw-r--r--system/test/mock/mock_stack_l2cap_interface.h1
-rw-r--r--system/test/mock/mock_stack_rfcomm_port_api.cc9
11 files changed, 167 insertions, 0 deletions
diff --git a/system/stack/include/l2cap_interface.h b/system/stack/include/l2cap_interface.h
index c3e32dcf36..af8d08d7d5 100644
--- a/system/stack/include/l2cap_interface.h
+++ b/system/stack/include/l2cap_interface.h
@@ -933,6 +933,23 @@ public:
**
******************************************************************************/
virtual bool L2CA_GetAclHandle(uint16_t lcid, uint16_t* acl_handle) = 0;
+
+ /*******************************************************************************
+ **
+ ** Function L2CA_GetLocalMtu
+ **
+ ** Description Given a local channel identifier, |lcid|, this function
+ ** returns the L2CAP local mtu, |local_mtu|. If
+ ** |lcid| is not known or is invalid, this function returns false and does not
+ ** modify the value pointed at by |local_mtu|.
+ **
+ ** Parameters: lcid: Local CID
+ ** local_mtu: Pointer to L2CAP local mtu must NOT be nullptr
+ **
+ ** Returns true if local_mtu lookup was successful
+ **
+ ******************************************************************************/
+ virtual bool L2CA_GetLocalMtu(uint16_t lcid, uint16_t* local_mtu) = 0;
};
Interface& get_interface();
diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h
index e2986740f1..260a30e1b0 100644
--- a/system/stack/include/port_api.h
+++ b/system/stack/include/port_api.h
@@ -483,4 +483,30 @@ void RFCOMM_Init(void);
******************************************************************************/
[[nodiscard]] int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask);
+/*******************************************************************************
+ *
+ * Function PORT_GetChannelInfo
+ *
+ * Description This function is called to get RFCOMM channel information
+ * by the handle of the port. All OUT parameters must NOT be nullptr.
+ *
+ * Parameters: handle - Handle of the port returned in the Open
+ * local_mtu - OUT local L2CAP MTU
+ * remote_mtu - OUT remote L2CAP MTU
+ * local_credit - OUT local RFCOMM credit
+ * remote_credit - OUT remote RFCOMM credit
+ * local_cid - OUT local L2CAP CID
+ * remote_cid - OUT remote L2CAP CID
+ * dlci - OUT dlci
+ * max_frame_size- OUT max frame size for RFCOMM
+ * acl_handle - OUT ACL handle
+ * mux_initiator - OUT is initiator of the RFCOMM multiplexer control channel
+ *
+ ******************************************************************************/
+[[nodiscard]] int PORT_GetChannelInfo(uint16_t handle, uint16_t* local_mtu, uint16_t* remote_mtu,
+ uint16_t* local_credit, uint16_t* remote_credit,
+ uint16_t* local_cid, uint16_t* remote_cid, uint16_t* dlci,
+ uint16_t* max_frame_size, uint16_t* acl_handle,
+ bool* mux_initiator);
+
#endif /* PORT_API_H */
diff --git a/system/stack/l2cap/internal/l2c_api.h b/system/stack/l2cap/internal/l2c_api.h
index 99c1f57781..e6a949a888 100644
--- a/system/stack/l2cap/internal/l2c_api.h
+++ b/system/stack/l2cap/internal/l2c_api.h
@@ -794,3 +794,20 @@ void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status);
**
******************************************************************************/
[[nodiscard]] bool L2CA_GetAclHandle(uint16_t lcid, uint16_t* acl_handle);
+
+/*******************************************************************************
+ **
+ ** Function L2CA_GetLocalMtu
+ **
+ ** Description Given a local channel identifier, |lcid|, this function
+ ** returns the L2CAP local mtu, |local_mtu|. If
+ ** |lcid| is not known or is invalid, this function returns false and does not
+ ** modify the value pointed at by |local_mtu|.
+ **
+ ** Parameters: lcid: Local CID
+ ** local_mtu: Pointer to L2CAP local mtu must NOT be nullptr
+ **
+ ** Returns true if local_mtu lookup was successful
+ **
+ ******************************************************************************/
+[[nodiscard]] bool L2CA_GetLocalMtu(uint16_t lcid, uint16_t* local_mtu);
diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc
index 68aacece21..7ae58fe77f 100644
--- a/system/stack/l2cap/l2c_api.cc
+++ b/system/stack/l2cap/l2c_api.cc
@@ -1763,6 +1763,33 @@ bool L2CA_GetAclHandle(uint16_t lcid, uint16_t* acl_handle) {
return true;
}
+/*******************************************************************************
+ **
+ ** Function L2CA_GetLocalMtu
+ **
+ ** Description Given a local channel identifier, |lcid|, this function
+ ** returns the L2CAP local mtu, |local_mtu|. If
+ ** |lcid| is not known or is invalid, this function returns false and does not
+ ** modify the value pointed at by |local_mtu|.
+ **
+ ** Parameters: lcid: Local CID
+ ** local_mtu: Pointer to L2CAP local mtu must NOT be nullptr
+ **
+ ** Returns true if local_mtu lookup was successful
+ **
+ ******************************************************************************/
+bool L2CA_GetLocalMtu(uint16_t lcid, uint16_t* local_mtu) {
+ log::assert_that(local_mtu != nullptr, "assert failed: local_mtu != nullptr");
+
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(nullptr, lcid);
+ if (p_ccb == nullptr) {
+ log::error("No CCB for CID:0x{:04x}", lcid);
+ return false;
+ }
+ *local_mtu = p_ccb->p_rcb->my_mtu;
+ return true;
+}
+
using namespace bluetooth;
#define DUMPSYS_TAG "shim::legacy::l2cap"
diff --git a/system/stack/l2cap/l2c_api.h b/system/stack/l2cap/l2c_api.h
index f89a5cc6ca..fc7faccc18 100644
--- a/system/stack/l2cap/l2c_api.h
+++ b/system/stack/l2cap/l2c_api.h
@@ -135,6 +135,8 @@ public:
bool is_local_cid) override;
[[nodiscard]] bool L2CA_GetAclHandle(uint16_t lcid, uint16_t* acl_handle) override;
+
+ [[nodiscard]] bool L2CA_GetLocalMtu(uint16_t lcid, uint16_t* local_mtu) override;
};
} // namespace l2cap
diff --git a/system/stack/l2cap/l2cap_api.cc b/system/stack/l2cap/l2cap_api.cc
index 2e1b12c7de..37caa2bc2a 100644
--- a/system/stack/l2cap/l2cap_api.cc
+++ b/system/stack/l2cap/l2cap_api.cc
@@ -262,3 +262,8 @@ void bluetooth::stack::l2cap::Impl::L2CA_SetMediaStreamChannel(uint16_t local_me
uint16_t* acl_handle) {
return ::L2CA_GetAclHandle(lcid, acl_handle);
}
+
+[[nodiscard]] bool bluetooth::stack::l2cap::Impl::L2CA_GetLocalMtu(uint16_t lcid,
+ uint16_t* local_mtu) {
+ return ::L2CA_GetLocalMtu(lcid, local_mtu);
+}
diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc
index 6786e88d02..0495026945 100644
--- a/system/stack/rfcomm/port_api.cc
+++ b/system/stack/rfcomm/port_api.cc
@@ -1194,3 +1194,51 @@ int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask) {
*sec_mask = p_port->sec_mask;
return PORT_SUCCESS;
}
+
+int PORT_GetChannelInfo(uint16_t handle, uint16_t* local_mtu, uint16_t* remote_mtu,
+ uint16_t* local_credit, uint16_t* remote_credit, uint16_t* local_cid,
+ uint16_t* remote_cid, uint16_t* dlci, uint16_t* max_frame_size,
+ uint16_t* acl_handle, bool* mux_initiator) {
+ log::verbose("PORT_GetChannelInfo() handle:{}", handle);
+
+ tPORT* p_port = get_port_from_handle(handle);
+ if (p_port == nullptr) {
+ log::error("Unable to get RFCOMM port control block bad handle:{}", handle);
+ return PORT_BAD_HANDLE;
+ }
+
+ if (!p_port->in_use || (p_port->state == PORT_CONNECTION_STATE_CLOSED)) {
+ return PORT_NOT_OPENED;
+ }
+
+ if (p_port->line_status) {
+ return PORT_LINE_ERR;
+ }
+
+ uint16_t rcid, ahandle, lmtu;
+ if (!stack::l2cap::get_interface().L2CA_GetRemoteChannelId(p_port->rfc.p_mcb->lcid, &rcid)) {
+ log::error("L2CA_GetRemoteChannelId failed, local cid: {}", p_port->rfc.p_mcb->lcid);
+ return PORT_PEER_FAILED;
+ }
+
+ if (!stack::l2cap::get_interface().L2CA_GetAclHandle(p_port->rfc.p_mcb->lcid, &ahandle)) {
+ log::error("L2CA_GetAclHandle failed, local cid: {}", p_port->rfc.p_mcb->lcid);
+ return PORT_PEER_FAILED;
+ }
+
+ if (!stack::l2cap::get_interface().L2CA_GetLocalMtu(p_port->rfc.p_mcb->lcid, &lmtu)) {
+ log::error("L2CA_GetLocalMtu failed, local cid: {}", p_port->rfc.p_mcb->lcid);
+ return PORT_PEER_FAILED;
+ }
+ *local_mtu = lmtu;
+ *remote_mtu = p_port->rfc.p_mcb->peer_l2cap_mtu + RFCOMM_MIN_OFFSET + 1;
+ *local_credit = p_port->credit_rx;
+ *remote_credit = p_port->credit_tx;
+ *local_cid = p_port->rfc.p_mcb->lcid;
+ *remote_cid = rcid;
+ *dlci = p_port->dlci;
+ *max_frame_size = p_port->mtu;
+ *acl_handle = ahandle;
+ *mux_initiator = p_port->rfc.p_mcb->is_initiator;
+ return PORT_SUCCESS;
+}
diff --git a/system/test/mock/mock_stack_l2cap_api.cc b/system/test/mock/mock_stack_l2cap_api.cc
index 3dd0ef991c..de117f06a9 100644
--- a/system/test/mock/mock_stack_l2cap_api.cc
+++ b/system/test/mock/mock_stack_l2cap_api.cc
@@ -76,6 +76,7 @@ struct L2CA_isMediaChannel L2CA_isMediaChannel;
struct L2CA_LeCreditDefault L2CA_LeCreditDefault;
struct L2CA_LeCreditThreshold L2CA_LeCreditThreshold;
struct L2CA_GetAclHandle L2CA_GetAclHandle;
+struct L2CA_GetLocalMtu L2CA_GetLocalMtu;
} // namespace stack_l2cap_api
} // namespace mock
@@ -255,6 +256,10 @@ bool L2CA_GetAclHandle(uint16_t lcid, uint16_t* acl_handle) {
inc_func_call_count(__func__);
return test::mock::stack_l2cap_api::L2CA_GetAclHandle(lcid, acl_handle);
}
+bool L2CA_GetLocalMtu(uint16_t lcid, uint16_t* local_mtu) {
+ inc_func_call_count(__func__);
+ return test::mock::stack_l2cap_api::L2CA_GetLocalMtu(lcid, local_mtu);
+}
// END mockcify generation
diff --git a/system/test/mock/mock_stack_l2cap_api.h b/system/test/mock/mock_stack_l2cap_api.h
index ed20c3438d..3f2e6dc72f 100644
--- a/system/test/mock/mock_stack_l2cap_api.h
+++ b/system/test/mock/mock_stack_l2cap_api.h
@@ -467,6 +467,16 @@ struct L2CA_GetAclHandle {
};
extern struct L2CA_GetAclHandle L2CA_GetAclHandle;
+// Name: L2CA_GetLocalMtu
+// Params: uint16_t lcid, uint16_t* local_mtu
+// Returns: bool
+struct L2CA_GetLocalMtu {
+ std::function<bool(uint16_t lcid, uint16_t* local_mtu)> body{
+ [](uint16_t /* lcid */, uint16_t* /* local_mtu */) { return false; }};
+ bool operator()(uint16_t lcid, uint16_t* local_mtu) { return body(lcid, local_mtu); }
+};
+extern struct L2CA_GetLocalMtu L2CA_GetLocalMtu;
+
} // namespace stack_l2cap_api
} // namespace mock
} // namespace test
diff --git a/system/test/mock/mock_stack_l2cap_interface.h b/system/test/mock/mock_stack_l2cap_interface.h
index 7756f4a4ed..f274f18643 100644
--- a/system/test/mock/mock_stack_l2cap_interface.h
+++ b/system/test/mock/mock_stack_l2cap_interface.h
@@ -107,6 +107,7 @@ public:
MOCK_METHOD(void, L2CA_Consolidate, (const RawAddress& identity_addr, const RawAddress& rpa));
MOCK_METHOD(bool, L2CA_GetAclHandle, (uint16_t lcid, uint16_t* acl_handle));
+ MOCK_METHOD(bool, L2CA_GetLocalMtu, (uint16_t lcid, uint16_t* local_mtu));
// Disconnect methods an active connection for both BR/EDR and BLE
MOCK_METHOD(bool, L2CA_DisconnectReq, (uint16_t cid));
diff --git a/system/test/mock/mock_stack_rfcomm_port_api.cc b/system/test/mock/mock_stack_rfcomm_port_api.cc
index e3dffbbf48..da6eefd3b9 100644
--- a/system/test/mock/mock_stack_rfcomm_port_api.cc
+++ b/system/test/mock/mock_stack_rfcomm_port_api.cc
@@ -101,6 +101,15 @@ int PORT_GetSecurityMask(uint16_t /* handle */, uint16_t* /* sec_mask */) {
inc_func_call_count(__func__);
return 0;
}
+int PORT_GetChannelInfo(uint16_t /* handle */, uint16_t* /* local_mtu */,
+ uint16_t* /* remote_mtu */, uint16_t* /* local_credit */,
+ uint16_t* /* remote_credit */, uint16_t* /* local_cid */,
+ uint16_t* /* remote_cid */, uint16_t* /* dlci */,
+ uint16_t* /* max_frame_size */, uint16_t* /* acl_handle */,
+ bool* /* mux_initiator */) {
+ inc_func_call_count(__func__);
+ return 0;
+}
void RFCOMM_Init(void) { inc_func_call_count(__func__); }
bool PORT_IsCollisionDetected(RawAddress /* bd_addr */) {
inc_func_call_count(__func__);