@@ -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
}
@@ -1781,7 +1795,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1781
1795
rsp = net_buf_pull_mem (buf , sizeof (* rsp ));
1782
1796
result = sys_le16_to_cpu (rsp -> result );
1783
1797
1784
- while ((ch = l2cap_lookup_ident (conn , ident ))) {
1798
+ while ((ch = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_RECONF_REQ ))) {
1785
1799
/* Stop timer started on REQ send. The timer is only set on one
1786
1800
* of the channels, but we don't want to make assumptions on
1787
1801
* which one it is.
@@ -1794,6 +1808,7 @@ static void le_ecred_reconf_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1794
1808
1795
1809
ch -> pending_rx_mtu = 0 ;
1796
1810
ch -> ident = 0U ;
1811
+ ch -> pending_req = 0U ;
1797
1812
1798
1813
if (ch -> chan .ops -> reconfigured ) {
1799
1814
ch -> chan .ops -> reconfigured (& ch -> chan );
@@ -1939,7 +1954,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1939
1954
1940
1955
LOG_DBG ("mtu 0x%04x mps 0x%04x credits 0x%04x result %u" , mtu , mps , credits , result );
1941
1956
1942
- chan = l2cap_lookup_ident (conn , ident );
1957
+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ );
1943
1958
if (chan ) {
1944
1959
psm = chan -> psm ;
1945
1960
} else {
@@ -1949,7 +1964,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1949
1964
switch (result ) {
1950
1965
case BT_L2CAP_LE_ERR_AUTHENTICATION :
1951
1966
case BT_L2CAP_LE_ERR_ENCRYPTION :
1952
- while ((chan = l2cap_lookup_ident (conn , ident ))) {
1967
+ while ((chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
1953
1968
1954
1969
/* Cancel RTX work */
1955
1970
k_work_cancel_delayable (& chan -> rtx_work );
@@ -1969,7 +1984,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
1969
1984
case BT_L2CAP_LE_ERR_SCID_IN_USE :
1970
1985
/* Some connections refused – not enough resources available */
1971
1986
case BT_L2CAP_LE_ERR_NO_RESOURCES :
1972
- while ((chan = l2cap_lookup_ident (conn , ident ))) {
1987
+ while ((chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
1973
1988
struct bt_l2cap_chan * c ;
1974
1989
1975
1990
/* Cancel RTX work */
@@ -2025,6 +2040,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2025
2040
chan -> tx .cid = dcid ;
2026
2041
2027
2042
chan -> ident = 0U ;
2043
+ chan -> pending_req = 0U ;
2028
2044
2029
2045
chan -> tx .mtu = mtu ;
2030
2046
chan -> tx .mps = mps ;
@@ -2045,7 +2061,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2045
2061
break ;
2046
2062
case BT_L2CAP_LE_ERR_PSM_NOT_SUPP :
2047
2063
default :
2048
- while ((chan = l2cap_remove_ident (conn , ident ))) {
2064
+ while ((chan = l2cap_remove_ident (conn , ident , BT_L2CAP_ECRED_CONN_REQ ))) {
2049
2065
bt_l2cap_chan_del (& chan -> chan );
2050
2066
}
2051
2067
break ;
@@ -2084,9 +2100,9 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2084
2100
if (result == BT_L2CAP_LE_SUCCESS ||
2085
2101
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
2086
2102
result == BT_L2CAP_LE_ERR_ENCRYPTION ) {
2087
- chan = l2cap_lookup_ident (conn , ident );
2103
+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_LE_CONN_REQ );
2088
2104
} else {
2089
- chan = l2cap_remove_ident (conn , ident );
2105
+ chan = l2cap_remove_ident (conn , ident , BT_L2CAP_LE_CONN_REQ );
2090
2106
}
2091
2107
2092
2108
if (!chan ) {
@@ -2099,6 +2115,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2099
2115
2100
2116
/* Reset ident since it got a response */
2101
2117
chan -> ident = 0U ;
2118
+ chan -> pending_req = 0U ;
2102
2119
2103
2120
switch (result ) {
2104
2121
case BT_L2CAP_LE_SUCCESS :
@@ -2158,7 +2175,17 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
2158
2175
return ;
2159
2176
}
2160
2177
2178
+ chan = l2cap_lookup_ident (conn , ident , BT_L2CAP_DISCONN_REQ );
2179
+ if (!chan ) {
2180
+ LOG_ERR ("Cannot find channel for ident %u" , ident );
2181
+ return ;
2182
+ }
2183
+
2161
2184
scid = sys_le16_to_cpu (rsp -> scid );
2185
+ if (scid != chan -> rx .cid ) {
2186
+ LOG_ERR ("Invalid scid 0x%04x" , scid );
2187
+ return ;
2188
+ }
2162
2189
2163
2190
LOG_DBG ("dcid 0x%04x scid 0x%04x" , sys_le16_to_cpu (rsp -> dcid ), scid );
2164
2191
@@ -2226,7 +2253,7 @@ static void reject_cmd(struct bt_l2cap *l2cap, uint8_t ident,
2226
2253
struct bt_conn * conn = l2cap -> chan .chan .conn ;
2227
2254
struct bt_l2cap_le_chan * chan ;
2228
2255
2229
- while ((chan = l2cap_remove_ident (conn , ident ))) {
2256
+ while ((chan = l2cap_remove_ident (conn , ident , ANY_OPCODE ))) {
2230
2257
bt_l2cap_chan_del (& chan -> chan );
2231
2258
}
2232
2259
}
@@ -3093,6 +3120,7 @@ int bt_l2cap_ecred_chan_reconfigure(struct bt_l2cap_chan **chans, uint16_t mtu)
3093
3120
ch = BT_L2CAP_LE_CHAN (chans [j ]);
3094
3121
3095
3122
ch -> ident = ident ;
3123
+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
3096
3124
ch -> pending_rx_mtu = mtu ;
3097
3125
3098
3126
net_buf_add_le16 (buf , ch -> rx .cid );
@@ -3180,6 +3208,7 @@ int bt_l2cap_ecred_chan_reconfigure_explicit(struct bt_l2cap_chan **chans, size_
3180
3208
ch = BT_L2CAP_LE_CHAN (chans [i ]);
3181
3209
3182
3210
ch -> ident = ident ;
3211
+ ch -> pending_req = BT_L2CAP_ECRED_RECONF_REQ ;
3183
3212
ch -> pending_rx_mtu = mtu ;
3184
3213
3185
3214
net_buf_add_le16 (buf , ch -> rx .cid );
@@ -3232,6 +3261,7 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
3232
3261
struct net_buf * buf ;
3233
3262
struct bt_l2cap_disconn_req * req ;
3234
3263
struct bt_l2cap_le_chan * le_chan ;
3264
+ uint8_t ident ;
3235
3265
3236
3266
if (!conn ) {
3237
3267
return - ENOTCONN ;
@@ -3246,14 +3276,16 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
3246
3276
3247
3277
LOG_DBG ("chan %p scid 0x%04x dcid 0x%04x" , chan , le_chan -> rx .cid , le_chan -> tx .cid );
3248
3278
3249
- le_chan -> ident = get_ident ();
3279
+ ident = get_ident ();
3250
3280
3251
- buf = l2cap_create_le_sig_pdu (BT_L2CAP_DISCONN_REQ ,
3252
- le_chan -> ident , sizeof (* req ));
3281
+ buf = l2cap_create_le_sig_pdu (BT_L2CAP_DISCONN_REQ , ident , sizeof (* req ));
3253
3282
if (!buf ) {
3254
3283
return - ENOMEM ;
3255
3284
}
3256
3285
3286
+ le_chan -> ident = ident ;
3287
+ le_chan -> pending_req = BT_L2CAP_DISCONN_REQ ;
3288
+
3257
3289
req = net_buf_add (buf , sizeof (* req ));
3258
3290
req -> dcid = sys_cpu_to_le16 (le_chan -> tx .cid );
3259
3291
req -> scid = sys_cpu_to_le16 (le_chan -> rx .cid );
0 commit comments