66 * SPDX-License-Identifier: Apache-2.0
77 */
88
9+ #include <zephyr/bluetooth/addr.h>
10+ #include <zephyr/bluetooth/conn.h>
911#include <zephyr/kernel.h>
1012#include <string.h>
1113#include <errno.h>
@@ -295,6 +297,28 @@ struct net_buf *bt_att_create_rsp_pdu(struct bt_att_chan *chan, uint8_t op);
295297
296298static void bt_att_sent (struct bt_l2cap_chan * ch );
297299
300+ static void att_disconnect (struct bt_att_chan * chan )
301+ {
302+ char addr [BT_ADDR_LE_STR_LEN ];
303+ int err ;
304+
305+ /* In rare circumstances we are "forced" to disconnect the ATT bearer and the ACL.
306+ * Examples of when this is right course of action is when there is an ATT timeout, we
307+ * receive an unexpected response from the server, or the response from the server is
308+ * invalid
309+ */
310+
311+ bt_addr_le_to_str (bt_conn_get_dst (chan -> att -> conn ), addr , sizeof (addr ));
312+ LOG_DBG ("ATT disconnecting device %s" , addr );
313+
314+ bt_att_disconnected (& chan -> chan .chan );
315+
316+ err = bt_conn_disconnect (chan -> chan .chan .conn , BT_HCI_ERR_REMOTE_USER_TERM_CONN );
317+ if (err ) {
318+ LOG_ERR ("Disconnecting failed (err %d)" , err );
319+ }
320+ }
321+
298322static void att_sent (void * user_data )
299323{
300324 struct bt_att_tx_meta_data * data = user_data ;
@@ -930,7 +954,8 @@ static uint8_t att_handle_rsp(struct bt_att_chan *chan, void *pdu, uint16_t len,
930954
931955 if (!chan -> req ) {
932956 LOG_WRN ("No pending ATT request" );
933- goto process ;
957+ att_disconnect (chan );
958+ return 0 ; /* Returning a non-0 value would attempt to send an error response */
934959 }
935960
936961 /* Check if request has been cancelled */
@@ -3139,9 +3164,7 @@ static void att_timeout(struct k_work *work)
31393164{
31403165 char addr [BT_ADDR_LE_STR_LEN ];
31413166 struct k_work_delayable * dwork = k_work_delayable_from_work (work );
3142- struct bt_att_chan * chan = CONTAINER_OF (dwork , struct bt_att_chan ,
3143- timeout_work );
3144- int err ;
3167+ struct bt_att_chan * chan = CONTAINER_OF (dwork , struct bt_att_chan , timeout_work );
31453168
31463169 bt_addr_le_to_str (bt_conn_get_dst (chan -> att -> conn ), addr , sizeof (addr ));
31473170 LOG_ERR ("ATT Timeout for device %s. Disconnecting..." , addr );
@@ -3154,17 +3177,13 @@ static void att_timeout(struct k_work *work)
31543177 * requests, commands, indications or notifications shall be sent to the
31553178 * target device on this ATT Bearer.
31563179 */
3157- bt_att_disconnected (& chan -> chan .chan );
31583180
31593181 /* The timeout state is local and can block new ATT operations, but does not affect the
31603182 * remote side. Disconnecting the GATT connection upon ATT timeout simplifies error handling
31613183 * for developers. This reduces rare failure conditions to a common one, allowing developers
31623184 * to handle unexpected disconnections without needing special cases for ATT timeouts.
31633185 */
3164- err = bt_conn_disconnect (chan -> chan .chan .conn , BT_HCI_ERR_REMOTE_USER_TERM_CONN );
3165- if (err ) {
3166- LOG_ERR ("Disconnecting failed (err %d)" , err );
3167- }
3186+ att_disconnect (chan );
31683187}
31693188
31703189static struct bt_att_chan * att_get_fixed_chan (struct bt_conn * conn )
0 commit comments