diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 5e6505e5410..f2ba61d8d2e 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -90,7 +90,6 @@ struct bt_att_chan { struct bt_att_req *req; struct k_fifo tx_queue; struct k_work_delayable timeout_work; - void (*sent)(struct bt_att_chan *chan); sys_snode_t node; }; @@ -133,17 +132,45 @@ static struct bt_att_req cancel; */ static k_tid_t att_handle_rsp_thread; -typedef void (*bt_att_chan_sent_t)(struct bt_att_chan *chan); +struct bt_att_tx_meta_data { + struct bt_att_chan *att_chan; + bt_conn_tx_cb_t func; + void *user_data; +}; -static bt_att_chan_sent_t chan_cb(struct net_buf *buf); -static bt_conn_tx_cb_t att_cb(bt_att_chan_sent_t cb); +struct bt_att_tx_meta { + struct bt_att_tx_meta_data *data; +}; + +#define bt_att_tx_meta_data(buf) (((struct bt_att_tx_meta *)net_buf_user_data(buf))->data) + +static struct bt_att_tx_meta_data tx_meta_data[CONFIG_BT_CONN_TX_MAX]; +K_FIFO_DEFINE(free_att_tx_meta_data); + +static struct bt_att_tx_meta_data *tx_meta_data_alloc(void) +{ + return k_fifo_get(&free_att_tx_meta_data, K_NO_WAIT); +} + +static inline void tx_meta_data_free(struct bt_att_tx_meta_data *data) +{ + __ASSERT_NO_MSG(data); + + (void)memset(data, 0, sizeof(*data)); + k_fifo_put(&free_att_tx_meta_data, data); +} + +static bt_conn_tx_cb_t chan_cb(const struct net_buf *buf); +static bt_conn_tx_cb_t att_cb(const struct net_buf *buf); static void att_chan_mtu_updated(struct bt_att_chan *updated_chan); static void bt_att_disconnected(struct bt_l2cap_chan *chan); void att_sent(struct bt_conn *conn, void *user_data) { - struct bt_l2cap_chan *chan = user_data; + struct bt_att_tx_meta_data *data = user_data; + struct bt_att_chan *att_chan = data->att_chan; + struct bt_l2cap_chan *chan = &att_chan->chan.chan; BT_DBG("conn %p chan %p", conn, chan); @@ -159,12 +186,12 @@ void att_sent(struct bt_conn *conn, void *user_data) * In case bt_l2cap_send_cb fails the buffer state and ownership are retained * so the buffer can be safely pushed back to the queue to be processed later. */ -static int chan_send(struct bt_att_chan *chan, struct net_buf *buf, - bt_att_chan_sent_t cb) +static int chan_send(struct bt_att_chan *chan, struct net_buf *buf) { struct bt_att_hdr *hdr; struct net_buf_simple_state state; int err; + struct bt_att_tx_meta_data *data = bt_att_tx_meta_data(buf); hdr = (void *)buf->data; @@ -191,8 +218,6 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf, return -EAGAIN; } - chan->sent = cb ? cb : chan_cb(buf); - if (hdr->code == BT_ATT_OP_SIGNED_WRITE_CMD) { return -ENOTSUP; } @@ -212,10 +237,12 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf, return -EINVAL; } + data->att_chan = chan; + /* bt_l2cap_chan_send does actually return the number of bytes * that could be sent immediately. */ - err = bt_l2cap_chan_send(&chan->chan.chan, buf); + err = bt_l2cap_chan_send_cb(&chan->chan.chan, buf, chan_cb(buf), data); if (err < 0) { return err; } @@ -229,6 +256,7 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf, err = bt_smp_sign(chan->att->conn, buf); if (err) { BT_ERR("Error signing data"); + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); return err; } @@ -236,11 +264,10 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf, net_buf_simple_save(&buf->b, &state); - chan->sent = cb ? cb : chan_cb(buf); + data->att_chan = chan; err = bt_l2cap_send_cb(chan->att->conn, BT_L2CAP_CID_ATT, - buf, att_cb(chan->sent), - &chan->chan.chan); + buf, att_cb(buf), data); if (err) { /* In case of an error has occurred restore the buffer state */ net_buf_simple_restore(&buf->b, &state); @@ -256,7 +283,7 @@ static int process_queue(struct bt_att_chan *chan, struct k_fifo *queue) buf = net_buf_get(queue, K_NO_WAIT); if (buf) { - err = chan_send(chan, buf, NULL); + err = chan_send(chan, buf); if (err) { /* Push it back if it could not be send */ k_queue_prepend(&queue->_queue, buf); @@ -288,7 +315,7 @@ static int chan_req_send(struct bt_att_chan *chan, struct bt_att_req *req) buf = req->buf; req->buf = NULL; - err = chan_send(chan, buf, NULL); + err = chan_send(chan, buf); if (err) { /* We still have the ownership of the buffer */ req->buf = buf; @@ -306,10 +333,6 @@ static void bt_att_sent(struct bt_l2cap_chan *ch) BT_DBG("chan %p", chan); - if (chan->sent) { - chan->sent(chan); - } - atomic_clear_bit(chan->flags, ATT_PENDING_SENT); if (!att) { @@ -343,37 +366,73 @@ static void bt_att_sent(struct bt_l2cap_chan *ch) (void)process_queue(chan, &att->tx_queue); } -static void chan_cfm_sent(struct bt_att_chan *chan) +static void chan_cfm_sent(struct bt_conn *conn, void *user_data) { + struct bt_att_tx_meta_data *data = user_data; + struct bt_att_chan *chan = data->att_chan; + BT_DBG("chan %p", chan); if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) { atomic_clear_bit(chan->flags, ATT_PENDING_CFM); } + + tx_meta_data_free(data); } -static void chan_rsp_sent(struct bt_att_chan *chan) +static void chan_rsp_sent(struct bt_conn *conn, void *user_data) { + struct bt_att_tx_meta_data *data = user_data; + struct bt_att_chan *chan = data->att_chan; + BT_DBG("chan %p", chan); if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) { atomic_clear_bit(chan->flags, ATT_PENDING_RSP); } + + tx_meta_data_free(data); } -static void chan_req_sent(struct bt_att_chan *chan) +static void chan_req_sent(struct bt_conn *conn, void *user_data) { + struct bt_att_tx_meta_data *data = user_data; + struct bt_att_chan *chan = data->att_chan; + BT_DBG("chan %p chan->req %p", chan, chan->req); /* Start timeout work */ if (chan->req) { k_work_reschedule(&chan->timeout_work, BT_ATT_TIMEOUT); } + + tx_meta_data_free(user_data); } -static bt_att_chan_sent_t chan_cb(struct net_buf *buf) +static void chan_tx_complete(struct bt_conn *conn, void *user_data) { - switch (att_op_get_type(buf->data[0])) { + struct bt_att_tx_meta_data *data = user_data; + struct bt_att_chan *chan = data->att_chan; + + BT_DBG("TX Complete chan %p CID 0x%04X", chan, chan->chan.tx.cid); + + if (data->func) { + data->func(conn, data->user_data); + } + + tx_meta_data_free(data); +} + +static void chan_unknown(struct bt_conn *conn, void *user_data) +{ + tx_meta_data_free(user_data); +} + +static bt_conn_tx_cb_t chan_cb(const struct net_buf *buf) +{ + const att_type_t op_type = att_op_get_type(buf->data[0]); + + switch (op_type) { case ATT_RESPONSE: return chan_rsp_sent; case ATT_CONFIRMATION: @@ -381,58 +440,66 @@ static bt_att_chan_sent_t chan_cb(struct net_buf *buf) case ATT_REQUEST: case ATT_INDICATION: return chan_req_sent; + case ATT_COMMAND: + case ATT_NOTIFICATION: + return chan_tx_complete; default: - return NULL; + __ASSERT(false, "Unknown op type 0x%02X", op_type); } + + return chan_unknown; } static void att_cfm_sent(struct bt_conn *conn, void *user_data) { - struct bt_l2cap_chan *ch = user_data; - struct bt_att_chan *chan = ATT_CHAN(ch); - - BT_DBG("conn %p chan %p", conn, chan); - - chan->sent = chan_cfm_sent; - att_sent(conn, user_data); + chan_cfm_sent(conn, user_data); } static void att_rsp_sent(struct bt_conn *conn, void *user_data) { - struct bt_l2cap_chan *ch = user_data; - struct bt_att_chan *chan = ATT_CHAN(ch); - - BT_DBG("conn %p chan %p", conn, chan); - - chan->sent = chan_rsp_sent; - att_sent(conn, user_data); + chan_rsp_sent(conn, user_data); } static void att_req_sent(struct bt_conn *conn, void *user_data) { - struct bt_l2cap_chan *ch = user_data; - struct bt_att_chan *chan = ATT_CHAN(ch); - - BT_DBG("conn %p chan %p", conn, chan); - - chan->sent = chan_req_sent; - att_sent(conn, user_data); + chan_req_sent(conn, user_data); } -static bt_conn_tx_cb_t att_cb(bt_att_chan_sent_t cb) +static void att_tx_complete(struct bt_conn *conn, void *user_data) { - if (cb == chan_rsp_sent) { + att_sent(conn, user_data); + chan_tx_complete(conn, user_data); +} + +static void att_unknown(struct bt_conn *conn, void *user_data) +{ + att_sent(conn, user_data); + chan_unknown(conn, user_data); +} + +static bt_conn_tx_cb_t att_cb(const struct net_buf *buf) +{ + const att_type_t op_type = att_op_get_type(buf->data[0]); + + switch (op_type) { + case ATT_RESPONSE: return att_rsp_sent; - } else if (cb == chan_cfm_sent) { + case ATT_CONFIRMATION: return att_cfm_sent; - } else if (cb == chan_req_sent) { + case ATT_REQUEST: + case ATT_INDICATION: return att_req_sent; - } else { - return att_sent; + case ATT_COMMAND: + case ATT_NOTIFICATION: + return att_tx_complete; + default: + __ASSERT(false, "Unknown op type 0x%02X", op_type); } + + return att_unknown; } struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t op, @@ -440,6 +507,7 @@ struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t op, { struct bt_att_hdr *hdr; struct net_buf *buf; + struct bt_att_tx_meta_data *data; if (len + sizeof(op) > chan->chan.tx.mtu) { BT_WARN("ATT MTU exceeded, max %u, wanted %zu", @@ -462,19 +530,27 @@ struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t op, return NULL; } + data = tx_meta_data_alloc(); + if (!data) { + BT_WARN("Unable to allocate ATT TX meta"); + net_buf_unref(buf); + return NULL; + } + + bt_att_tx_meta_data(buf) = data; + hdr = net_buf_add(buf, sizeof(*hdr)); hdr->code = op; return buf; } -static int bt_att_chan_send(struct bt_att_chan *chan, struct net_buf *buf, - bt_att_chan_sent_t cb) +static int bt_att_chan_send(struct bt_att_chan *chan, struct net_buf *buf) { BT_DBG("chan %p flags %lu code 0x%02x", chan, atomic_get(chan->flags), ((struct bt_att_hdr *)buf->data)->code); - return chan_send(chan, buf, cb); + return chan_send(chan, buf); } static void att_send_process(struct bt_att *att) @@ -489,7 +565,7 @@ static void att_send_process(struct bt_att *att) } SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { - err = bt_att_chan_send(chan, buf, NULL); + err = bt_att_chan_send(chan, buf); if (err >= 0) { break; } @@ -501,12 +577,11 @@ static void att_send_process(struct bt_att *att) } } -static void bt_att_chan_send_rsp(struct bt_att_chan *chan, struct net_buf *buf, - bt_att_chan_sent_t cb) +static void bt_att_chan_send_rsp(struct bt_att_chan *chan, struct net_buf *buf) { int err; - err = bt_att_chan_send(chan, buf, cb); + err = bt_att_chan_send(chan, buf); if (err) { /* Responses need to be sent back using the same channel */ net_buf_put(&chan->tx_queue, buf); @@ -534,7 +609,7 @@ static void send_err_rsp(struct bt_att_chan *chan, uint8_t req, uint16_t handle, rsp->handle = sys_cpu_to_le16(handle); rsp->error = err; - bt_att_chan_send_rsp(chan, buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, buf); } static uint8_t att_mtu_req(struct bt_att_chan *chan, struct net_buf *buf) @@ -575,7 +650,7 @@ static uint8_t att_mtu_req(struct bt_att_chan *chan, struct net_buf *buf) rsp = net_buf_add(pdu, sizeof(*rsp)); rsp->mtu = sys_cpu_to_le16(mtu_server); - bt_att_chan_send_rsp(chan, pdu, chan_rsp_sent); + bt_att_chan_send_rsp(chan, pdu); /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part F] page 484: * @@ -817,6 +892,7 @@ static uint8_t att_find_info_rsp(struct bt_att_chan *chan, uint16_t start_handle bt_gatt_foreach_attr(start_handle, end_handle, find_info_cb, &data); if (!data.rsp) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond since handle is set */ send_err_rsp(chan, BT_ATT_OP_FIND_INFO_REQ, start_handle, @@ -824,7 +900,7 @@ static uint8_t att_find_info_rsp(struct bt_att_chan *chan, uint16_t start_handle return 0; } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -981,6 +1057,7 @@ static uint8_t att_find_type_rsp(struct bt_att_chan *chan, uint16_t start_handle /* If error has not been cleared, no service has been found */ if (data.err) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond since handle is set */ send_err_rsp(chan, BT_ATT_OP_FIND_TYPE_REQ, start_handle, @@ -988,7 +1065,7 @@ static uint8_t att_find_type_rsp(struct bt_att_chan *chan, uint16_t start_handle return 0; } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1213,6 +1290,7 @@ static uint8_t att_read_type_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid, bt_gatt_foreach_attr(start_handle, end_handle, read_type_cb, &data); if (data.err) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Response here since handle is set */ send_err_rsp(chan, BT_ATT_OP_READ_TYPE_REQ, start_handle, @@ -1220,7 +1298,7 @@ static uint8_t att_read_type_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid, return 0; } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1335,13 +1413,14 @@ static uint8_t att_read_rsp(struct bt_att_chan *chan, uint8_t op, uint8_t rsp, /* In case of error discard data and respond with an error */ if (data.err) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(chan, op, handle, data.err); return 0; } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1419,6 +1498,7 @@ static uint8_t att_read_mult_req(struct bt_att_chan *chan, struct net_buf *buf) /* Stop reading in case of error */ if (data.err) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(chan, BT_ATT_OP_READ_MULT_REQ, handle, @@ -1427,7 +1507,7 @@ static uint8_t att_read_mult_req(struct bt_att_chan *chan, struct net_buf *buf) } } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1513,6 +1593,7 @@ static uint8_t att_read_mult_vl_req(struct bt_att_chan *chan, struct net_buf *bu /* Stop reading in case of error */ if (data.err) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(chan, BT_ATT_OP_READ_MULT_VL_REQ, handle, @@ -1521,7 +1602,7 @@ static uint8_t att_read_mult_vl_req(struct bt_att_chan *chan, struct net_buf *bu } } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1631,6 +1712,7 @@ static uint8_t att_read_group_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid bt_gatt_foreach_attr(start_handle, end_handle, read_group_cb, &data); if (!data.rsp->len) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(chan, BT_ATT_OP_READ_GROUP_REQ, start_handle, @@ -1638,7 +1720,7 @@ static uint8_t att_read_group_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid return 0; } - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -1780,6 +1862,7 @@ static uint8_t att_write_rsp(struct bt_att_chan *chan, uint8_t req, uint8_t rsp, if (data.err) { /* In case of error discard data and respond with an error */ if (rsp) { + tx_meta_data_free(bt_att_tx_meta_data(data.buf)); net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(chan, req, handle, data.err); @@ -1788,7 +1871,7 @@ static uint8_t att_write_rsp(struct bt_att_chan *chan, uint8_t req, uint8_t rsp, } if (data.buf) { - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); } return 0; @@ -1917,7 +2000,7 @@ static uint8_t att_prep_write_rsp(struct bt_att_chan *chan, uint16_t handle, net_buf_add(data.buf, len); memcpy(rsp->value, value, len); - bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, data.buf); return 0; } @@ -2060,7 +2143,7 @@ static uint8_t att_exec_write_rsp(struct bt_att_chan *chan, uint8_t flags) return BT_ATT_ERR_UNLIKELY; } - bt_att_chan_send_rsp(chan, buf, chan_rsp_sent); + bt_att_chan_send_rsp(chan, buf); return 0; } @@ -2344,7 +2427,7 @@ static uint8_t att_indicate(struct bt_att_chan *chan, struct net_buf *buf) return 0; } - bt_att_chan_send_rsp(chan, buf, chan_cfm_sent); + bt_att_chan_send_rsp(chan, buf); return 0; } @@ -2680,6 +2763,7 @@ static void att_reset(struct bt_att *att) #if CONFIG_BT_ATT_PREPARE_COUNT > 0 /* Discard queued buffers */ while ((buf = net_buf_slist_get(&att->prep_queue))) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); } #endif /* CONFIG_BT_ATT_PREPARE_COUNT > 0 */ @@ -2691,6 +2775,7 @@ static void att_reset(struct bt_att *att) #endif /* CONFIG_BT_EATT */ while ((buf = net_buf_get(&att->tx_queue, K_NO_WAIT))) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); } @@ -2726,6 +2811,7 @@ static void att_chan_detach(struct bt_att_chan *chan) /* Release pending buffers */ while ((buf = net_buf_get(&chan->tx_queue, K_NO_WAIT))) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); } @@ -2846,11 +2932,13 @@ static uint8_t att_req_retry(struct bt_att_chan *att_chan) } if (req->encode(buf, req->len, req->user_data)) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); return BT_ATT_ERR_UNLIKELY; } - if (chan_send(att_chan, buf, NULL)) { + if (chan_send(att_chan, buf)) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); return BT_ATT_ERR_UNLIKELY; } @@ -3287,6 +3375,10 @@ static void bt_eatt_init(void) void bt_att_init(void) { + for (size_t i = 0; i < ARRAY_SIZE(tx_meta_data); i++) { + k_fifo_put(&free_att_tx_meta_data, &tx_meta_data[i]); + } + bt_gatt_init(); if (IS_ENABLED(CONFIG_BT_EATT)) { @@ -3367,6 +3459,7 @@ void bt_att_req_free(struct bt_att_req *req) BT_DBG("req %p", req); if (req->buf) { + tx_meta_data_free(bt_att_tx_meta_data(req->buf)); net_buf_unref(req->buf); req->buf = NULL; } @@ -3374,8 +3467,7 @@ void bt_att_req_free(struct bt_att_req *req) k_mem_slab_free(&req_slab, (void **)&req); } -int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb, - void *user_data) +int bt_att_send(struct bt_conn *conn, struct net_buf *buf) { struct bt_att *att; @@ -3384,18 +3476,11 @@ int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb, att = att_get(conn); if (!att) { + tx_meta_data_free(bt_att_tx_meta_data(buf)); net_buf_unref(buf); return -ENOTCONN; } - /* If callback is set use the fixed channel since bt_l2cap_chan_send - * cannot be used with a custom user_data. - */ - if (cb) { - return bt_l2cap_send_cb(conn, BT_L2CAP_CID_ATT, buf, cb, - user_data); - } - net_buf_put(&att->tx_queue, buf); att_send_process(att); @@ -3527,3 +3612,18 @@ bool bt_att_out_of_sync_sent_on_fixed(struct bt_conn *conn) att_chan = ATT_CHAN(l2cap_chan); return atomic_test_bit(att_chan->flags, ATT_OUT_OF_SYNC_SENT); } + +void bt_att_set_tx_meta_data(struct net_buf *buf, bt_conn_tx_cb_t func, void *user_data) +{ + struct bt_att_tx_meta_data *data = bt_att_tx_meta_data(buf); + + data->func = func; + data->user_data = user_data; +} + +bool bt_att_tx_meta_data_match(const struct net_buf *buf, bt_conn_tx_cb_t func, + const void *user_data) +{ + return ((bt_att_tx_meta_data(buf)->func == func) && + (bt_att_tx_meta_data(buf)->user_data == user_data)); +} diff --git a/subsys/bluetooth/host/att_internal.h b/subsys/bluetooth/host/att_internal.h index a8902335887..dd03b444b99 100644 --- a/subsys/bluetooth/host/att_internal.h +++ b/subsys/bluetooth/host/att_internal.h @@ -290,8 +290,7 @@ struct bt_att_req *bt_att_req_alloc(k_timeout_t timeout); void bt_att_req_free(struct bt_att_req *req); /* Send ATT PDU over a connection */ -int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb, - void *user_data); +int bt_att_send(struct bt_conn *conn, struct net_buf *buf); /* Send ATT Request over a connection */ int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req); @@ -317,3 +316,8 @@ void bt_att_clear_out_of_sync_sent(struct bt_conn *conn); /* Check if BT_ATT_ERR_DB_OUT_OF_SYNC has been sent on the fixed ATT channel */ bool bt_att_out_of_sync_sent_on_fixed(struct bt_conn *conn); + +void bt_att_set_tx_meta_data(struct net_buf *buf, bt_conn_tx_cb_t func, void *user_data); + +bool bt_att_tx_meta_data_match(const struct net_buf *buf, bt_conn_tx_cb_t func, + const void *user_data); diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index f9401551c79..b18876e667c 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -2078,10 +2078,9 @@ static struct net_buf *nfy_mult[CONFIG_BT_MAX_CONN]; static int gatt_notify_mult_send(struct bt_conn *conn, struct net_buf **buf) { - struct nfy_mult_data *data = nfy_mult_user_data(*buf); int ret; - ret = bt_att_send(conn, *buf, data->func, data->user_data); + ret = bt_att_send(conn, *buf); if (ret < 0) { net_buf_unref(*buf); } @@ -2132,7 +2131,7 @@ static int gatt_notify_mult(struct bt_conn *conn, uint16_t handle, * the existing buffer and proceed to create a new one */ if (*buf && ((net_buf_tailroom(*buf) < sizeof(*nfy) + params->len) || - !nfy_mult_data_match(*buf, params->func, params->user_data))) { + !bt_att_tx_meta_data_match(*buf, params->func, params->user_data))) { int ret; ret = gatt_notify_mult_send(conn, buf); @@ -2147,9 +2146,8 @@ static int gatt_notify_mult(struct bt_conn *conn, uint16_t handle, if (!*buf) { return -ENOMEM; } - /* Set user_data so it can be restored when sending */ - nfy_mult_user_data(*buf)->func = params->func; - nfy_mult_user_data(*buf)->user_data = params->user_data; + + bt_att_set_tx_meta_data(*buf, params->func, params->user_data); } BT_DBG("handle 0x%04x len %u", handle, params->len); @@ -2212,7 +2210,8 @@ static int gatt_notify(struct bt_conn *conn, uint16_t handle, net_buf_add(buf, params->len); memcpy(nfy->value, params->data, params->len); - return bt_att_send(conn, buf, params->func, params->user_data); + bt_att_set_tx_meta_data(buf, params->func, params->user_data); + return bt_att_send(conn, buf); } static void gatt_indicate_rsp(struct bt_conn *conn, uint8_t err, @@ -4425,7 +4424,7 @@ int bt_gatt_write_without_response_cb(struct bt_conn *conn, uint16_t handle, BT_DBG("handle 0x%04x length %u", handle, length); - return bt_att_send(conn, buf, func, user_data); + return bt_att_send(conn, buf); } static int gatt_exec_encode(struct net_buf *buf, size_t len, void *user_data)