@@ -80,8 +80,11 @@ NET_BUF_POOL_FIXED_DEFINE(disc_pool, 1,
8080 sizeof (struct bt_l2cap_disconn_req )),
8181 CONFIG_BT_CONN_TX_USER_DATA_SIZE , NULL );
8282
83- #define l2cap_lookup_ident (conn , ident ) __l2cap_lookup_ident(conn, ident, false)
84- #define l2cap_remove_ident (conn , ident ) __l2cap_lookup_ident(conn, ident, true)
83+ #define ANY_OPCODE 0x100
84+ #define l2cap_lookup_ident (conn , ident , req_opcode ) \
85+ __l2cap_lookup_ident(conn, ident, req_opcode, false)
86+ #define l2cap_remove_ident (conn , ident , req_opcode ) \
87+ __l2cap_lookup_ident(conn, ident, req_opcode, true)
8588
8689static sys_slist_t servers = SYS_SLIST_STATIC_INIT (& servers );
8790#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
@@ -139,13 +142,15 @@ static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
139142}
140143
141144static struct bt_l2cap_le_chan *
142- __l2cap_lookup_ident (struct bt_conn * conn , uint16_t ident , bool remove )
145+ __l2cap_lookup_ident (struct bt_conn * conn , uint16_t ident , uint16_t req_opcode , bool remove )
143146{
144147 struct bt_l2cap_chan * chan ;
145148 sys_snode_t * prev = NULL ;
146149
147150 SYS_SLIST_FOR_EACH_CONTAINER (& conn -> channels , chan , node ) {
148- if (BT_L2CAP_LE_CHAN (chan )-> ident == ident ) {
151+ if ((BT_L2CAP_LE_CHAN (chan )-> ident == ident ) &&
152+ ((BT_L2CAP_LE_CHAN (chan )-> pending_req == req_opcode ) ||
153+ (req_opcode == ANY_OPCODE ))) {
149154 if (remove ) {
150155 sys_slist_remove (& conn -> channels , prev ,
151156 & chan -> node );
@@ -303,7 +308,7 @@ static void l2cap_rtx_timeout(struct k_work *work)
303308 bt_l2cap_chan_del (& chan -> chan );
304309
305310 /* Remove other channels if pending on the same ident */
306- while ((chan = l2cap_remove_ident (conn , chan -> ident ))) {
311+ while ((chan = l2cap_remove_ident (conn , chan -> ident , chan -> pending_req ))) {
307312 bt_l2cap_chan_del (& chan -> chan );
308313 }
309314}
@@ -523,15 +528,23 @@ static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
523528{
524529 struct net_buf * buf ;
525530 struct bt_l2cap_le_conn_req * req ;
531+ uint8_t ident ;
526532
527- ch -> ident = get_ident ();
533+ ident = get_ident ();
528534
529- buf = l2cap_create_le_sig_pdu (BT_L2CAP_LE_CONN_REQ ,
530- ch -> ident , sizeof (* req ));
535+ buf = l2cap_create_le_sig_pdu (BT_L2CAP_LE_CONN_REQ , ident , sizeof (* req ));
531536 if (!buf ) {
532537 return - ENOMEM ;
533538 }
534539
540+ /* TODO Ident handling/setting should ideally be done in l2cap_chan_send_req after the
541+ * request is successfully sent on the channel but will require special considerations for
542+ * functions such as l2cap_ecred_conn_req and bt_l2cap_ecred_chan_reconfigure where the
543+ * ident is set for multiple channels, but the request is only sent on one.
544+ */
545+ ch -> ident = ident ;
546+ ch -> pending_req = BT_L2CAP_LE_CONN_REQ ;
547+
535548 req = net_buf_add (buf , sizeof (* req ));
536549 req -> psm = sys_cpu_to_le16 (ch -> psm );
537550 req -> scid = sys_cpu_to_le16 (ch -> rx .cid );
@@ -590,6 +603,7 @@ static int l2cap_ecred_conn_req(struct bt_l2cap_chan **chan, int channels)
590603 "The MTU shall be the same for channels in the same request." );
591604
592605 ch -> ident = ident ;
606+ ch -> pending_req = BT_L2CAP_ECRED_CONN_REQ ;
593607
594608 net_buf_add_le16 (buf , ch -> rx .cid );
595609 }
@@ -1785,7 +1799,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
17851799 rsp = net_buf_pull_mem (buf , sizeof (* rsp ));
17861800 result = sys_le16_to_cpu (rsp -> result );
17871801
1788- while ((ch = l2cap_lookup_ident (conn , ident ))) {
1802+ while ((ch = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_RECONF_REQ ))) {
17891803 /* Stop timer started on REQ send. The timer is only set on one
17901804 * of the channels, but we don't want to make assumptions on
17911805 * which one it is.
@@ -1798,6 +1812,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
17981812
17991813 ch -> pending_rx_mtu = 0 ;
18001814 ch -> ident = 0U ;
1815+ ch -> pending_req = 0U ;
18011816
18021817 if (ch -> chan .ops -> reconfigured ) {
18031818 ch -> chan .ops -> reconfigured (& ch -> chan );
@@ -1943,7 +1958,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19431958
19441959 LOG_DBG ("mtu 0x%04x mps 0x%04x credits 0x%04x result %u" , mtu , mps , credits , result );
19451960
1946- chan = l2cap_lookup_ident (conn , ident );
1961+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ );
19471962 if (chan ) {
19481963 psm = chan -> psm ;
19491964 } else {
@@ -1953,7 +1968,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19531968 switch (result ) {
19541969 case BT_L2CAP_LE_ERR_AUTHENTICATION :
19551970 case BT_L2CAP_LE_ERR_ENCRYPTION :
1956- while ((chan = l2cap_lookup_ident (conn , ident ))) {
1971+ while ((chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
19571972
19581973 /* Cancel RTX work */
19591974 k_work_cancel_delayable (& chan -> rtx_work );
@@ -1973,7 +1988,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
19731988 case BT_L2CAP_LE_ERR_SCID_IN_USE :
19741989 /* Some connections refused – not enough resources available */
19751990 case BT_L2CAP_LE_ERR_NO_RESOURCES :
1976- while ((chan = l2cap_lookup_ident (conn , ident ))) {
1991+ while ((chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
19771992 struct bt_l2cap_chan * c ;
19781993
19791994 /* Cancel RTX work */
@@ -2029,6 +2044,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20292044 chan -> tx .cid = dcid ;
20302045
20312046 chan -> ident = 0U ;
2047+ chan -> pending_req = 0U ;
20322048
20332049 chan -> tx .mtu = mtu ;
20342050 chan -> tx .mps = mps ;
@@ -2049,7 +2065,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20492065 break ;
20502066 case BT_L2CAP_LE_ERR_PSM_NOT_SUPP :
20512067 default :
2052- while ((chan = l2cap_remove_ident (conn , ident ))) {
2068+ while ((chan = l2cap_remove_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
20532069 bt_l2cap_chan_del (& chan -> chan );
20542070 }
20552071 break ;
@@ -2088,9 +2104,9 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
20882104 if (result == BT_L2CAP_LE_SUCCESS ||
20892105 result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
20902106 result == BT_L2CAP_LE_ERR_ENCRYPTION ) {
2091- chan = l2cap_lookup_ident (conn , ident );
2107+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_LE_CONN_REQ );
20922108 } else {
2093- chan = l2cap_remove_ident (conn , ident );
2109+ chan = l2cap_remove_ident (conn , ident , BT_L2CAP_LE_CONN_REQ );
20942110 }
20952111
20962112 if (!chan ) {
@@ -2103,6 +2119,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
21032119
21042120 /* Reset ident since it got a response */
21052121 chan -> ident = 0U ;
2122+ chan -> pending_req = 0U ;
21062123
21072124 switch (result ) {
21082125 case BT_L2CAP_LE_SUCCESS :
@@ -2162,7 +2179,17 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
21622179 return ;
21632180 }
21642181
2182+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_DISCONN_REQ );
2183+ if (!chan ) {
2184+ LOG_ERR ("Cannot find channel for ident %u" , ident );
2185+ return ;
2186+ }
2187+
21652188 scid = sys_le16_to_cpu (rsp -> scid );
2189+ if (scid != chan -> rx .cid ) {
2190+ LOG_ERR ("Invalid scid 0x%04x" , scid );
2191+ return ;
2192+ }
21662193
21672194 LOG_DBG ("dcid 0x%04x scid 0x%04x" , sys_le16_to_cpu (rsp -> dcid ), scid );
21682195
@@ -2230,7 +2257,7 @@ static void reject_cmd(struct bt_l2cap *l2cap, uint8_t ident,
22302257 struct bt_conn * conn = l2cap -> chan .chan .conn ;
22312258 struct bt_l2cap_le_chan * chan ;
22322259
2233- while ((chan = l2cap_remove_ident (conn , ident ))) {
2260+ while ((chan = l2cap_remove_ident (conn , ident , ANY_OPCODE ))) {
22342261 bt_l2cap_chan_del (& chan -> chan );
22352262 }
22362263}
@@ -3097,6 +3124,7 @@ int bt_l2cap_ecred_chan_reconfigure(struct bt_l2cap_chan **chans, uint16_t mtu)
30973124 ch = BT_L2CAP_LE_CHAN (chans [j ]);
30983125
30993126 ch -> ident = ident ;
3127+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
31003128 ch -> pending_rx_mtu = mtu ;
31013129
31023130 net_buf_add_le16 (buf , ch -> rx .cid );
@@ -3184,6 +3212,7 @@ int bt_l2cap_ecred_chan_reconfigure_explicit(struct bt_l2cap_chan **chans, size_
31843212 ch = BT_L2CAP_LE_CHAN (chans [i ]);
31853213
31863214 ch -> ident = ident ;
3215+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
31873216 ch -> pending_rx_mtu = mtu ;
31883217
31893218 net_buf_add_le16 (buf , ch -> rx .cid );
@@ -3236,6 +3265,7 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
32363265 struct net_buf * buf ;
32373266 struct bt_l2cap_disconn_req * req ;
32383267 struct bt_l2cap_le_chan * le_chan ;
3268+ uint8_t ident ;
32393269
32403270 if (!conn ) {
32413271 return - ENOTCONN ;
@@ -3250,14 +3280,16 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
32503280
32513281 LOG_DBG ("chan %p scid 0x%04x dcid 0x%04x" , chan , le_chan -> rx .cid , le_chan -> tx .cid );
32523282
3253- le_chan -> ident = get_ident ();
3283+ ident = get_ident ();
32543284
3255- buf = l2cap_create_le_sig_pdu (BT_L2CAP_DISCONN_REQ ,
3256- le_chan -> ident , sizeof (* req ));
3285+ buf = l2cap_create_le_sig_pdu (BT_L2CAP_DISCONN_REQ , ident , sizeof (* req ));
32573286 if (!buf ) {
32583287 return - ENOMEM ;
32593288 }
32603289
3290+ le_chan -> ident = ident ;
3291+ le_chan -> pending_req = BT_L2CAP_DISCONN_REQ ;
3292+
32613293 req = net_buf_add (buf , sizeof (* req ));
32623294 req -> dcid = sys_cpu_to_le16 (le_chan -> tx .cid );
32633295 req -> scid = sys_cpu_to_le16 (le_chan -> rx .cid );
0 commit comments