Bluetooth: l2CAP_BR: Fix the response cannot be sent out issue
There is an issue that the L2CAP connect response function `l2cap_br_conn_req_reply()` is called first. And then the ACL disconnect function `bt_conn_disconnect()` is called following. But the packet of `bt_conn_disconnect()` appears on the HCI bus first. Add a flag `L2CAP_FLAG_DISCONNECT_ACL` to flag whether it is needed to disconnect ACL connection. Set the flag `L2CAP_FLAG_DISCONNECT_ACL` when result of the L2CAP channel conn rsp is `BT_L2CAP_BR_ERR_SEC_BLOCK`. Add a l2cap packet sent out callback `l2cap_br_conn_rsp_sent_cb()`. When the callback triggered, disconnect the ACL connect with `BT_HCI_ERR_AUTH_FAIL` if the flag `L2CAP_FLAG_DISCONNECT_ACL` has been set. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
parent
cdc2f2a52c
commit
9a04dfd85e
1 changed files with 31 additions and 2 deletions
|
@ -75,6 +75,9 @@ enum {
|
|||
|
||||
/* fixed channels flags */
|
||||
L2CAP_FLAG_FIXED_CONNECTED, /* fixed connected */
|
||||
|
||||
/* Auth failed, disconnect ACL */
|
||||
L2CAP_FLAG_DISCONNECT_ACL, /* Disconnect ACL */
|
||||
};
|
||||
|
||||
static sys_slist_t br_servers;
|
||||
|
@ -859,6 +862,22 @@ l2cap_br_conn_security(struct bt_l2cap_chan *chan, const uint16_t psm)
|
|||
return L2CAP_CONN_SECURITY_REJECT;
|
||||
}
|
||||
|
||||
static void l2cap_br_conn_rsp_sent_cb(struct bt_conn *conn, void *user_data, int err)
|
||||
{
|
||||
uint16_t scid = POINTER_TO_UINT(user_data);
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
chan = bt_l2cap_br_lookup_tx_cid(conn, scid);
|
||||
if (!chan) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether the ACL connection needs to be disconnected. */
|
||||
if (atomic_test_and_clear_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_DISCONNECT_ACL)) {
|
||||
bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
static void l2cap_br_send_conn_rsp(struct bt_conn *conn, uint16_t scid,
|
||||
uint16_t dcid, uint8_t ident, uint16_t result)
|
||||
{
|
||||
|
@ -884,7 +903,10 @@ static void l2cap_br_send_conn_rsp(struct bt_conn *conn, uint16_t scid,
|
|||
rsp->status = sys_cpu_to_le16(BT_L2CAP_CS_NO_INFO);
|
||||
}
|
||||
|
||||
l2cap_send(conn, BT_L2CAP_CID_BR_SIG, buf);
|
||||
if (bt_l2cap_br_send_cb(conn, BT_L2CAP_CID_BR_SIG, buf, l2cap_br_conn_rsp_sent_cb,
|
||||
UINT_TO_POINTER(scid))) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static int l2cap_br_conn_req_reply(struct bt_l2cap_chan *chan, uint16_t result)
|
||||
|
@ -1084,6 +1106,8 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
case L2CAP_CONN_SECURITY_REJECT:
|
||||
default:
|
||||
result = BT_L2CAP_BR_ERR_SEC_BLOCK;
|
||||
/* Set disconnect ACL flag. */
|
||||
atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_DISCONNECT_ACL);
|
||||
break;
|
||||
}
|
||||
/* Reply on connection request as acceptor */
|
||||
|
@ -1092,7 +1116,12 @@ static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
|
|||
if (result != BT_L2CAP_BR_SUCCESS) {
|
||||
/* Disconnect link when security rules were violated */
|
||||
if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
|
||||
bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
|
||||
/*
|
||||
* Disconnect the ACL after the packet of response has been sent.
|
||||
* The `L2CAP_FLAG_DISCONNECT_ACL` is used to flag whether ACL disconnect
|
||||
* request needs to be sent when the L2CAP conn rsp sent out callback is
|
||||
* triggered.
|
||||
*/
|
||||
} else if (result == BT_L2CAP_BR_PENDING) {
|
||||
/* Recover the ident when conn is pending */
|
||||
br_chan->ident = ident;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue