@@ -112,18 +112,6 @@ K_MEM_SLAB_DEFINE(chan_slab, sizeof(struct bt_att_chan),
112
112
__alignof__(struct bt_att_chan ));
113
113
static struct bt_att_req cancel ;
114
114
115
- static void att_req_destroy (struct bt_att_req * req )
116
- {
117
- BT_DBG ("req %p" , req );
118
-
119
- if (req -> buf ) {
120
- net_buf_unref (req -> buf );
121
- req -> buf = NULL ;
122
- }
123
-
124
- bt_att_req_free (req );
125
- }
126
-
127
115
typedef void (* bt_att_chan_sent_t )(struct bt_att_chan * chan );
128
116
129
117
static bt_att_chan_sent_t chan_cb (struct net_buf * buf );
@@ -201,19 +189,14 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf,
201
189
202
190
chan -> sent = cb ? cb : chan_cb (buf );
203
191
204
- /* Take a ref since bt_l2cap_send_cb takes ownership of the buffer */
205
192
err = bt_l2cap_send_cb (chan -> att -> conn , BT_L2CAP_CID_ATT ,
206
- net_buf_ref (buf ), att_cb (chan -> sent ),
207
- & chan -> chan .chan );
208
- if (!err ) {
209
- net_buf_unref (buf );
210
- return 0 ;
193
+ buf , att_cb (chan -> sent ),
194
+ & chan -> chan .chan );
195
+ if (err ) {
196
+ net_buf_simple_restore (& buf -> b , & state );
211
197
}
212
198
213
- net_buf_simple_restore (& buf -> b , & state );
214
-
215
199
return err ;
216
-
217
200
}
218
201
219
202
static int process_queue (struct bt_att_chan * chan , struct k_fifo * queue )
@@ -239,6 +222,7 @@ static int process_queue(struct bt_att_chan *chan, struct k_fifo *queue)
239
222
/* Send requests without taking tx_sem */
240
223
static int chan_req_send (struct bt_att_chan * chan , struct bt_att_req * req )
241
224
{
225
+ struct net_buf * buf ;
242
226
int err ;
243
227
244
228
if (chan -> chan .tx .mtu < net_buf_frags_len (req -> buf )) {
@@ -250,19 +234,14 @@ static int chan_req_send(struct bt_att_chan *chan, struct bt_att_req *req)
250
234
251
235
chan -> req = req ;
252
236
253
- /* Save request state so it can be resent */
254
- net_buf_simple_save (& req -> buf -> b , & req -> state );
237
+ /* Release since bt_l2cap_send_cb takes ownership of the buffer */
238
+ buf = req -> buf ;
239
+ req -> buf = NULL ;
255
240
256
- /* Keep a reference for resending the req in case the security
257
- * needs to be changed.
258
- */
259
- err = chan_send (chan , net_buf_ref (req -> buf ), NULL );
241
+ err = chan_send (chan , buf , NULL );
260
242
if (err ) {
261
- /* Drop the extra reference if buffer could not be sent but
262
- * don't reset the buffer as it will likelly be pushed back to
263
- * request queue to be send later.
264
- */
265
- net_buf_unref (req -> buf );
243
+ /* We still have the ownership of the buffer */
244
+ req -> buf = buf ;
266
245
}
267
246
268
247
return err ;
@@ -607,19 +586,13 @@ static uint8_t att_handle_rsp(struct bt_att_chan *chan, void *pdu, uint16_t len,
607
586
goto process ;
608
587
}
609
588
610
- /* Release original buffer */
611
- if (chan -> req -> buf ) {
612
- net_buf_unref (chan -> req -> buf );
613
- chan -> req -> buf = NULL ;
614
- }
615
-
616
589
/* Reset func so it can be reused by the callback */
617
590
func = chan -> req -> func ;
618
591
chan -> req -> func = NULL ;
619
592
params = chan -> req -> user_data ;
620
593
621
594
/* free allocated request so its memory can be reused */
622
- att_req_destroy (chan -> req );
595
+ bt_att_req_free (chan -> req );
623
596
chan -> req = NULL ;
624
597
625
598
process :
@@ -2040,11 +2013,6 @@ static uint8_t att_error_rsp(struct bt_att_chan *chan, struct net_buf *buf)
2040
2013
goto done ;
2041
2014
}
2042
2015
2043
- if (chan -> req -> buf ) {
2044
- /* Restore state to be resent */
2045
- net_buf_simple_restore (& chan -> req -> buf -> b , & chan -> req -> state );
2046
- }
2047
-
2048
2016
err = rsp -> error ;
2049
2017
#if defined(CONFIG_BT_SMP )
2050
2018
/* Check if error can be handled by elevating security. */
@@ -2530,7 +2498,7 @@ static void att_reset(struct bt_att *att)
2530
2498
req -> user_data );
2531
2499
}
2532
2500
2533
- att_req_destroy (req );
2501
+ bt_att_req_free (req );
2534
2502
}
2535
2503
2536
2504
k_mem_slab_free (& att_slab , (void * * )& att );
@@ -2646,12 +2614,43 @@ static void bt_att_disconnected(struct bt_l2cap_chan *chan)
2646
2614
}
2647
2615
2648
2616
#if defined(CONFIG_BT_SMP )
2617
+ static uint8_t att_req_retry (struct bt_att_chan * att_chan )
2618
+ {
2619
+ struct bt_att_req * req = att_chan -> req ;
2620
+ struct net_buf * buf ;
2621
+
2622
+ /* Resend buffer */
2623
+ if (!req -> encode ) {
2624
+ /* This request does not support resending */
2625
+ return BT_ATT_ERR_AUTHENTICATION ;
2626
+ }
2627
+
2628
+
2629
+ buf = bt_att_chan_create_pdu (att_chan , req -> att_op , req -> len );
2630
+ if (!buf ) {
2631
+ return BT_ATT_ERR_UNLIKELY ;
2632
+ }
2633
+
2634
+ if (req -> encode (buf , req -> len , req -> user_data )) {
2635
+ net_buf_unref (buf );
2636
+ return BT_ATT_ERR_UNLIKELY ;
2637
+ }
2638
+
2639
+ if (chan_send (att_chan , buf , NULL )) {
2640
+ net_buf_unref (buf );
2641
+ return BT_ATT_ERR_UNLIKELY ;
2642
+ }
2643
+
2644
+ return BT_ATT_ERR_SUCCESS ;
2645
+ }
2646
+
2649
2647
static void bt_att_encrypt_change (struct bt_l2cap_chan * chan ,
2650
2648
uint8_t hci_status )
2651
2649
{
2652
2650
struct bt_att_chan * att_chan = ATT_CHAN (chan );
2653
2651
struct bt_l2cap_le_chan * ch = BT_L2CAP_LE_CHAN (chan );
2654
2652
struct bt_conn * conn = ch -> chan .conn ;
2653
+ uint8_t err ;
2655
2654
2656
2655
BT_DBG ("chan %p conn %p handle %u sec_level 0x%02x status 0x%02x" , ch ,
2657
2656
conn , conn -> handle , conn -> sec_level , hci_status );
@@ -2686,14 +2685,10 @@ static void bt_att_encrypt_change(struct bt_l2cap_chan *chan,
2686
2685
2687
2686
BT_DBG ("Retrying" );
2688
2687
2689
- /* Resend buffer */
2690
-
2691
- /* Since packets are created in ATT and released in L2CAP we need to
2692
- * take a new reference to "create" the packet in ATT again.
2693
- */
2694
- if (chan_send (att_chan , net_buf_ref (att_chan -> req -> buf ), NULL )) {
2695
- net_buf_unref (att_chan -> req -> buf );
2696
- att_handle_rsp (att_chan , NULL , 0 , BT_ATT_ERR_AUTHENTICATION );
2688
+ err = att_req_retry (att_chan );
2689
+ if (err ) {
2690
+ BT_DBG ("Retry failed (%d)" , err );
2691
+ att_handle_rsp (att_chan , NULL , 0 , err );
2697
2692
}
2698
2693
}
2699
2694
#endif /* CONFIG_BT_SMP */
@@ -2932,6 +2927,7 @@ struct bt_att_req *bt_att_req_alloc(k_timeout_t timeout)
2932
2927
2933
2928
/* Reserve space for request */
2934
2929
if (k_mem_slab_alloc (& req_slab , (void * * )& req , timeout )) {
2930
+ BT_DBG ("No space for req" );
2935
2931
return NULL ;
2936
2932
}
2937
2933
@@ -2946,6 +2942,11 @@ void bt_att_req_free(struct bt_att_req *req)
2946
2942
{
2947
2943
BT_DBG ("req %p" , req );
2948
2944
2945
+ if (req -> buf ) {
2946
+ net_buf_unref (req -> buf );
2947
+ req -> buf = NULL ;
2948
+ }
2949
+
2949
2950
k_mem_slab_free (& req_slab , (void * * )& req );
2950
2951
}
2951
2952
@@ -3003,8 +3004,6 @@ int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req)
3003
3004
3004
3005
att = att_get (conn );
3005
3006
if (!att ) {
3006
- net_buf_unref (req -> buf );
3007
- req -> buf = NULL ;
3008
3007
return - ENOTCONN ;
3009
3008
}
3010
3009
@@ -3037,7 +3036,7 @@ static bool bt_att_chan_req_cancel(struct bt_att_chan *chan,
3037
3036
3038
3037
chan -> req = & cancel ;
3039
3038
3040
- att_req_destroy (req );
3039
+ bt_att_req_free (req );
3041
3040
3042
3041
return true;
3043
3042
}
@@ -3068,5 +3067,5 @@ void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req)
3068
3067
/* Remove request from the list */
3069
3068
sys_slist_find_and_remove (& att -> reqs , & req -> node );
3070
3069
3071
- att_req_destroy (req );
3070
+ bt_att_req_free (req );
3072
3071
}
0 commit comments