From e97413057a468be4f4654471c8981b9c6186677d Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 11 Nov 2021 12:29:05 +0100 Subject: [PATCH] Bluetooth: Host: Fix type mismatch in bt_gatt_cancel `bt_gatt_cancel` takes a `bt_gatt_.._params` pointer. The `params` pointer is mistakenly passed on to `bt_att_req_cancel`, which expects a `bt_att_req`. This change makes bt_gatt_cancel locate the `req` and pass that to `bt_att_req_cancel`. Signed-off-by: Aleksander Wasaznik Co-authored-by: Emil Gydesen --- include/bluetooth/gatt.h | 18 +++++++++++++++--- subsys/bluetooth/host/att.c | 26 ++++++++++++++++++++++++++ subsys/bluetooth/host/att_internal.h | 7 +++++++ subsys/bluetooth/host/gatt.c | 17 ++++++++++++++++- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index 08366b8d052..3ba0a1027ec 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -1675,10 +1675,22 @@ int bt_gatt_resubscribe(uint8_t id, const bt_addr_le_t *peer, int bt_gatt_unsubscribe(struct bt_conn *conn, struct bt_gatt_subscribe_params *params); -/** @brief Cancel GATT pending request +/** @brief Try to cancel the first pending request identified by @p params. * - * @param conn Connection object. - * @param params Requested params address. + * This function does not release @p params for reuse. The usual callbacks + * for the request still apply. A successful cancel simulates a + * #BT_ATT_ERR_UNLIKELY response from the server. + * + * This function can cancel the following request functions: + * - #bt_gatt_exchange_mtu + * - #bt_gatt_discover + * - #bt_gatt_read + * - #bt_gatt_write + * - #bt_gatt_subscribe + * - #bt_gatt_unsubscribe + * + * @param conn The connection the request was issued on. + * @param params The address `params` used in the request function call. */ void bt_gatt_cancel(struct bt_conn *conn, void *params); diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 5cbbd44fc10..d9ae558936c 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -3228,3 +3228,29 @@ void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req) bt_att_req_free(req); } + +struct bt_att_req *bt_att_find_req_by_user_data(struct bt_conn *conn, const void *user_data) +{ + struct bt_att *att; + struct bt_att_chan *chan; + struct bt_att_req *req; + + att = att_get(conn); + if (!att) { + return NULL; + } + + SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { + if (chan->req->user_data == user_data) { + return chan->req; + } + } + + SYS_SLIST_FOR_EACH_CONTAINER(&att->reqs, req, node) { + if (req->user_data == user_data) { + return req; + } + } + + return NULL; +} diff --git a/subsys/bluetooth/host/att_internal.h b/subsys/bluetooth/host/att_internal.h index e794351be3d..a02fad0981e 100644 --- a/subsys/bluetooth/host/att_internal.h +++ b/subsys/bluetooth/host/att_internal.h @@ -304,3 +304,10 @@ int bt_eatt_connect(struct bt_conn *conn, uint8_t num_channels); /* Disconnect EATT channels */ int bt_eatt_disconnect(struct bt_conn *conn); + +/** @brief Find a pending ATT request by its user_data pointer. + * @param conn The connection the request was issued on. + * @param user_data The pointer value to look for. + * @return The found request. NULL if not found. + */ +struct bt_att_req *bt_att_find_req_by_user_data(struct bt_conn *conn, const void *user_data); diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 448c05885b3..21a07d8a19b 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -4650,7 +4650,22 @@ int bt_gatt_unsubscribe(struct bt_conn *conn, void bt_gatt_cancel(struct bt_conn *conn, void *params) { - bt_att_req_cancel(conn, params); + struct bt_att_req *req; + bt_att_func_t func = NULL; + + k_sched_lock(); + + req = bt_att_find_req_by_user_data(conn, params); + if (req) { + func = req->func; + bt_att_req_cancel(conn, req); + } + + k_sched_unlock(); + + if (func) { + func(conn, BT_ATT_ERR_UNLIKELY, NULL, 0, params); + } } static void add_subscriptions(struct bt_conn *conn)