@@ -80,8 +80,11 @@ NET_BUF_POOL_FIXED_DEFINE(disc_pool, 1,
80
80
sizeof (struct bt_l2cap_disconn_req )),
81
81
CONFIG_BT_CONN_TX_USER_DATA_SIZE , NULL );
82
82
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)
85
88
86
89
static sys_slist_t servers = SYS_SLIST_STATIC_INIT (& servers );
87
90
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
@@ -139,13 +142,15 @@ static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
139
142
}
140
143
141
144
static 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 )
143
146
{
144
147
struct bt_l2cap_chan * chan ;
145
148
sys_snode_t * prev = NULL ;
146
149
147
150
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 ))) {
149
154
if (remove ) {
150
155
sys_slist_remove (& conn -> channels , prev ,
151
156
& chan -> node );
@@ -303,7 +308,7 @@ static void l2cap_rtx_timeout(struct k_work *work)
303
308
bt_l2cap_chan_del (& chan -> chan );
304
309
305
310
/* 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 ))) {
307
312
bt_l2cap_chan_del (& chan -> chan );
308
313
}
309
314
}
@@ -523,15 +528,23 @@ static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
523
528
{
524
529
struct net_buf * buf ;
525
530
struct bt_l2cap_le_conn_req * req ;
531
+ uint8_t ident ;
526
532
527
- ch -> ident = get_ident ();
533
+ ident = get_ident ();
528
534
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 ));
531
536
if (!buf ) {
532
537
return - ENOMEM ;
533
538
}
534
539
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
+
535
548
req = net_buf_add (buf , sizeof (* req ));
536
549
req -> psm = sys_cpu_to_le16 (ch -> psm );
537
550
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)
590
603
"The MTU shall be the same for channels in the same request." );
591
604
592
605
ch -> ident = ident ;
606
+ ch -> pending_req = BT_L2CAP_ECRED_CONN_REQ ;
593
607
594
608
net_buf_add_le16 (buf , ch -> rx .cid );
595
609
}
@@ -1785,7 +1799,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1785
1799
rsp = net_buf_pull_mem (buf , sizeof (* rsp ));
1786
1800
result = sys_le16_to_cpu (rsp -> result );
1787
1801
1788
- while ((ch = l2cap_lookup_ident (conn , ident ))) {
1802
+ while ((ch = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_RECONF_REQ ))) {
1789
1803
/* Stop timer started on REQ send. The timer is only set on one
1790
1804
* of the channels, but we don't want to make assumptions on
1791
1805
* which one it is.
@@ -1798,6 +1812,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1798
1812
1799
1813
ch -> pending_rx_mtu = 0 ;
1800
1814
ch -> ident = 0U ;
1815
+ ch -> pending_req = 0U ;
1801
1816
1802
1817
if (ch -> chan .ops -> reconfigured ) {
1803
1818
ch -> chan .ops -> reconfigured (& ch -> chan );
@@ -1943,7 +1958,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1943
1958
1944
1959
LOG_DBG ("mtu 0x%04x mps 0x%04x credits 0x%04x result %u" , mtu , mps , credits , result );
1945
1960
1946
- chan = l2cap_lookup_ident (conn , ident );
1961
+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ );
1947
1962
if (chan ) {
1948
1963
psm = chan -> psm ;
1949
1964
} else {
@@ -1953,7 +1968,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1953
1968
switch (result ) {
1954
1969
case BT_L2CAP_LE_ERR_AUTHENTICATION :
1955
1970
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 ))) {
1957
1972
1958
1973
/* Cancel RTX work */
1959
1974
k_work_cancel_delayable (& chan -> rtx_work );
@@ -1973,7 +1988,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1973
1988
case BT_L2CAP_LE_ERR_SCID_IN_USE :
1974
1989
/* Some connections refused – not enough resources available */
1975
1990
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 ))) {
1977
1992
struct bt_l2cap_chan * c ;
1978
1993
1979
1994
/* Cancel RTX work */
@@ -2029,6 +2044,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2029
2044
chan -> tx .cid = dcid ;
2030
2045
2031
2046
chan -> ident = 0U ;
2047
+ chan -> pending_req = 0U ;
2032
2048
2033
2049
chan -> tx .mtu = mtu ;
2034
2050
chan -> tx .mps = mps ;
@@ -2049,7 +2065,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2049
2065
break ;
2050
2066
case BT_L2CAP_LE_ERR_PSM_NOT_SUPP :
2051
2067
default :
2052
- while ((chan = l2cap_remove_ident (conn , ident ))) {
2068
+ while ((chan = l2cap_remove_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
2053
2069
bt_l2cap_chan_del (& chan -> chan );
2054
2070
}
2055
2071
break ;
@@ -2088,9 +2104,9 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2088
2104
if (result == BT_L2CAP_LE_SUCCESS ||
2089
2105
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
2090
2106
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 );
2092
2108
} else {
2093
- chan = l2cap_remove_ident (conn , ident );
2109
+ chan = l2cap_remove_ident (conn , ident , BT_L2CAP_LE_CONN_REQ );
2094
2110
}
2095
2111
2096
2112
if (!chan ) {
@@ -2103,6 +2119,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2103
2119
2104
2120
/* Reset ident since it got a response */
2105
2121
chan -> ident = 0U ;
2122
+ chan -> pending_req = 0U ;
2106
2123
2107
2124
switch (result ) {
2108
2125
case BT_L2CAP_LE_SUCCESS :
@@ -2162,7 +2179,17 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2162
2179
return ;
2163
2180
}
2164
2181
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
+
2165
2188
scid = sys_le16_to_cpu (rsp -> scid );
2189
+ if (scid != chan -> rx .cid ) {
2190
+ LOG_ERR ("Invalid scid 0x%04x" , scid );
2191
+ return ;
2192
+ }
2166
2193
2167
2194
LOG_DBG ("dcid 0x%04x scid 0x%04x" , sys_le16_to_cpu (rsp -> dcid ), scid );
2168
2195
@@ -2230,7 +2257,7 @@ static void reject_cmd(struct bt_l2cap *l2cap, uint8_t ident,
2230
2257
struct bt_conn * conn = l2cap -> chan .chan .conn ;
2231
2258
struct bt_l2cap_le_chan * chan ;
2232
2259
2233
- while ((chan = l2cap_remove_ident (conn , ident ))) {
2260
+ while ((chan = l2cap_remove_ident (conn , ident , ANY_OPCODE ))) {
2234
2261
bt_l2cap_chan_del (& chan -> chan );
2235
2262
}
2236
2263
}
@@ -3097,6 +3124,7 @@ int bt_l2cap_ecred_chan_reconfigure(struct bt_l2cap_chan **chans, uint16_t mtu)
3097
3124
ch = BT_L2CAP_LE_CHAN (chans [j ]);
3098
3125
3099
3126
ch -> ident = ident ;
3127
+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
3100
3128
ch -> pending_rx_mtu = mtu ;
3101
3129
3102
3130
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_
3184
3212
ch = BT_L2CAP_LE_CHAN (chans [i ]);
3185
3213
3186
3214
ch -> ident = ident ;
3215
+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
3187
3216
ch -> pending_rx_mtu = mtu ;
3188
3217
3189
3218
net_buf_add_le16 (buf , ch -> rx .cid );
@@ -3236,6 +3265,7 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
3236
3265
struct net_buf * buf ;
3237
3266
struct bt_l2cap_disconn_req * req ;
3238
3267
struct bt_l2cap_le_chan * le_chan ;
3268
+ uint8_t ident ;
3239
3269
3240
3270
if (!conn ) {
3241
3271
return - ENOTCONN ;
@@ -3250,14 +3280,16 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
3250
3280
3251
3281
LOG_DBG ("chan %p scid 0x%04x dcid 0x%04x" , chan , le_chan -> rx .cid , le_chan -> tx .cid );
3252
3282
3253
- le_chan -> ident = get_ident ();
3283
+ ident = get_ident ();
3254
3284
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 ));
3257
3286
if (!buf ) {
3258
3287
return - ENOMEM ;
3259
3288
}
3260
3289
3290
+ le_chan -> ident = ident ;
3291
+ le_chan -> pending_req = BT_L2CAP_DISCONN_REQ ;
3292
+
3261
3293
req = net_buf_add (buf , sizeof (* req ));
3262
3294
req -> dcid = sys_cpu_to_le16 (le_chan -> tx .cid );
3263
3295
req -> scid = sys_cpu_to_le16 (le_chan -> rx .cid );
0 commit comments