diff --git a/drivers/bluetooth/nble/rpc_deserialize.c b/drivers/bluetooth/nble/rpc_deserialize.c index 8bb0f5374c0..29ef88cbbbf 100644 --- a/drivers/bluetooth/nble/rpc_deserialize.c +++ b/drivers/bluetooth/nble/rpc_deserialize.c @@ -557,8 +557,9 @@ static void deserialize_control(uint8_t fn_index, struct net_buf *buf) rpc_init_cb(struct_data.version, true); } break; - break; + default: panic(-1); + break; } } diff --git a/subsys/bluetooth/host/avdtp.c b/subsys/bluetooth/host/avdtp.c index ad34c0b51fc..193f0cce2e1 100644 --- a/subsys/bluetooth/host/avdtp.c +++ b/subsys/bluetooth/host/avdtp.c @@ -38,20 +38,10 @@ #define AVDTP_GET_PKT_TYPE(hdr) ((hdr & 0x0c) >> AVDTP_PKT_POSITION) #define AVDTP_GET_SIG_ID(s) (s & AVDTP_SIGID_MASK) -typedef int (*bt_avdtp_func_t)(struct bt_avdtp *session, - struct bt_avdtp_req *req); - static struct bt_avdtp_event_cb *event_cb; static struct bt_avdtp_seid_lsep *lseps; -struct bt_avdtp_req { - uint8_t signal_id; - uint8_t transaction_id; - bt_avdtp_func_t func; - struct k_delayed_work timeout_work; -}; - #define AVDTP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_avdtp, br_chan.chan) #define AVDTP_KWORK(_work) CONTAINER_OF(_work, struct bt_avdtp_req,\ diff --git a/subsys/bluetooth/host/avdtp_internal.h b/subsys/bluetooth/host/avdtp_internal.h index 7f8ae396ea5..0733cfddd80 100644 --- a/subsys/bluetooth/host/avdtp_internal.h +++ b/subsys/bluetooth/host/avdtp_internal.h @@ -87,6 +87,19 @@ #define BT_AVDTP_MIN_SEID 0x01 #define BT_AVDTP_MAX_SEID 0x3E +struct bt_avdtp; +struct bt_avdtp_req; + +typedef int (*bt_avdtp_func_t)(struct bt_avdtp *session, + struct bt_avdtp_req *req); + +struct bt_avdtp_req { + uint8_t signal_id; + uint8_t transaction_id; + bt_avdtp_func_t func; + struct k_delayed_work timeout_work; +}; + struct bt_avdtp_single_sig_hdr { uint8_t hdr; uint8_t signal_id; diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index d3011b87b65..5b9c6af14f0 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1020,12 +1020,32 @@ static bool send_buf(struct bt_conn *conn, struct net_buf *buf) static struct k_poll_signal conn_change = K_POLL_SIGNAL_INITIALIZER(); +static void conn_cleanup(struct bt_conn *conn) +{ + struct net_buf *buf; + + /* Give back any allocated buffers */ + while ((buf = net_buf_get(&conn->tx_queue, K_NO_WAIT))) { + net_buf_unref(buf); + } + + BT_ASSERT(!conn->pending_pkts); + + bt_conn_reset_rx_state(conn); + + /* Release the reference we took for the very first + * state transition. + */ + bt_conn_unref(conn); +} + int bt_conn_prepare_events(struct k_poll_event events[]) { int i, ev_count = 0; BT_DBG(""); + conn_change.signaled = 0; k_poll_event_init(&events[ev_count++], K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &conn_change); @@ -1036,6 +1056,12 @@ int bt_conn_prepare_events(struct k_poll_event events[]) continue; } + if (conn->state == BT_CONN_DISCONNECTED && + atomic_test_and_clear_bit(conn->flags, BT_CONN_CLEANUP)) { + conn_cleanup(conn); + continue; + } + if (conn->state != BT_CONN_CONNECTED) { continue; } @@ -1058,23 +1084,10 @@ void bt_conn_process_tx(struct bt_conn *conn) BT_DBG("conn %p", conn); - if (conn->state != BT_CONN_CONNECTED) { + if (conn->state == BT_CONN_DISCONNECTED && + atomic_test_and_clear_bit(conn->flags, BT_CONN_CLEANUP)) { BT_DBG("handle %u disconnected - cleaning up", conn->handle); - - /* Give back any allocated buffers */ - while ((buf = net_buf_get(&conn->tx_queue, K_NO_WAIT))) { - net_buf_unref(buf); - } - - BT_ASSERT(!conn->pending_pkts); - - bt_conn_reset_rx_state(conn); - - /* Release the reference we took for the very first - * state transition. - */ - bt_conn_unref(conn); - + conn_cleanup(conn); return; } @@ -1170,8 +1183,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) k_delayed_work_cancel(&conn->le.update_work); } - net_buf_put(&conn->tx_queue, - bt_conn_create_pdu(NULL, 0)); + atomic_set_bit(conn->flags, BT_CONN_CLEANUP); + k_poll_signal(&conn_change, 0); /* The last ref will be dropped by the tx_thread */ } else if (old_state == BT_CONN_CONNECT) { /* conn->err will be set in this case */ diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index dd1a9e01913..aec5925e423 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -23,6 +23,7 @@ enum { BT_CONN_BR_PAIRING, /* BR connection in pairing context */ BT_CONN_BR_NOBOND, /* SSP no bond pairing tracker */ BT_CONN_BR_PAIRING_INITIATOR, /* local host starts authentication */ + BT_CONN_CLEANUP, /* Disconnected, pending cleanup */ /* Total number of flags - must be at the end of the enum */ BT_CONN_NUM_FLAGS, diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 643c6a31d1f..9f08dbd995a 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -765,6 +765,7 @@ static void remove_subscriptions(struct bt_conn *conn) gatt_subscription_remove(conn, prev, params); } else { update_subscription(conn, params); + prev = node; } } }