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 ;
@@ -945,7 +969,8 @@ static uint8_t att_handle_rsp(struct bt_att_chan *chan, void *pdu, uint16_t len,
945969
946970 if (!chan -> req ) {
947971 LOG_WRN ("No pending ATT request" );
948- goto process ;
972+ att_disconnect (chan );
973+ return 0 ; /* Returning a non-0 value would attempt to send an error response */
949974 }
950975
951976 /* Check if request has been cancelled */
@@ -3154,9 +3179,7 @@ static void att_timeout(struct k_work *work)
31543179{
31553180 char addr [BT_ADDR_LE_STR_LEN ];
31563181 struct k_work_delayable * dwork = k_work_delayable_from_work (work );
3157- struct bt_att_chan * chan = CONTAINER_OF (dwork , struct bt_att_chan ,
3158- timeout_work );
3159- int err ;
3182+ struct bt_att_chan * chan = CONTAINER_OF (dwork , struct bt_att_chan , timeout_work );
31603183
31613184 bt_addr_le_to_str (bt_conn_get_dst (chan -> att -> conn ), addr , sizeof (addr ));
31623185 LOG_ERR ("ATT Timeout for device %s. Disconnecting..." , addr );
@@ -3169,17 +3192,13 @@ static void att_timeout(struct k_work *work)
31693192 * requests, commands, indications or notifications shall be sent to the
31703193 * target device on this ATT Bearer.
31713194 */
3172- bt_att_disconnected (& chan -> chan .chan );
31733195
31743196 /* The timeout state is local and can block new ATT operations, but does not affect the
31753197 * remote side. Disconnecting the GATT connection upon ATT timeout simplifies error handling
31763198 * for developers. This reduces rare failure conditions to a common one, allowing developers
31773199 * to handle unexpected disconnections without needing special cases for ATT timeouts.
31783200 */
3179- err = bt_conn_disconnect (chan -> chan .chan .conn , BT_HCI_ERR_REMOTE_USER_TERM_CONN );
3180- if (err ) {
3181- LOG_ERR ("Disconnecting failed (err %d)" , err );
3182- }
3201+ att_disconnect (chan );
31833202}
31843203
31853204static struct bt_att_chan * att_get_fixed_chan (struct bt_conn * conn )
0 commit comments