Bluetooth: GATT: Allocate request from a memory slab
This should reduce the footprint on applications that do a lot of requests i.e have a lot of subscriptions. Fixes #21103 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
f256625ad4
commit
d278cdc3d7
6 changed files with 73 additions and 42 deletions
|
@ -43,23 +43,6 @@ extern "C" {
|
||||||
#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe
|
#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe
|
||||||
#define BT_ATT_ERR_OUT_OF_RANGE 0xff
|
#define BT_ATT_ERR_OUT_OF_RANGE 0xff
|
||||||
|
|
||||||
typedef void (*bt_att_func_t)(struct bt_conn *conn, u8_t err,
|
|
||||||
const void *pdu, u16_t length,
|
|
||||||
void *user_data);
|
|
||||||
typedef void (*bt_att_destroy_t)(void *user_data);
|
|
||||||
|
|
||||||
/* ATT request context */
|
|
||||||
struct bt_att_req {
|
|
||||||
sys_snode_t node;
|
|
||||||
bt_att_func_t func;
|
|
||||||
bt_att_destroy_t destroy;
|
|
||||||
struct net_buf_simple_state state;
|
|
||||||
struct net_buf *buf;
|
|
||||||
#if defined(CONFIG_BT_SMP)
|
|
||||||
bool retrying;
|
|
||||||
#endif /* CONFIG_BT_SMP */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -879,7 +879,6 @@ typedef void (*bt_gatt_indicate_func_t)(struct bt_conn *conn,
|
||||||
|
|
||||||
/** @brief GATT Indicate Value parameters */
|
/** @brief GATT Indicate Value parameters */
|
||||||
struct bt_gatt_indicate_params {
|
struct bt_gatt_indicate_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
/** Notification Attribute UUID type */
|
/** Notification Attribute UUID type */
|
||||||
const struct bt_uuid *uuid;
|
const struct bt_uuid *uuid;
|
||||||
/** Indicate Attribute object*/
|
/** Indicate Attribute object*/
|
||||||
|
@ -963,7 +962,6 @@ u16_t bt_gatt_get_mtu(struct bt_conn *conn);
|
||||||
|
|
||||||
/** @brief GATT Exchange MTU parameters */
|
/** @brief GATT Exchange MTU parameters */
|
||||||
struct bt_gatt_exchange_params {
|
struct bt_gatt_exchange_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
/** Response callback */
|
/** Response callback */
|
||||||
void (*func)(struct bt_conn *conn, u8_t err,
|
void (*func)(struct bt_conn *conn, u8_t err,
|
||||||
struct bt_gatt_exchange_params *params);
|
struct bt_gatt_exchange_params *params);
|
||||||
|
@ -1040,7 +1038,6 @@ enum {
|
||||||
|
|
||||||
/** @brief GATT Discover Attributes parameters */
|
/** @brief GATT Discover Attributes parameters */
|
||||||
struct bt_gatt_discover_params {
|
struct bt_gatt_discover_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
/** Discover UUID type */
|
/** Discover UUID type */
|
||||||
struct bt_uuid *uuid;
|
struct bt_uuid *uuid;
|
||||||
/** Discover attribute callback */
|
/** Discover attribute callback */
|
||||||
|
@ -1121,7 +1118,6 @@ typedef u8_t (*bt_gatt_read_func_t)(struct bt_conn *conn, u8_t err,
|
||||||
* @param uuid 2 or 16 octet UUID
|
* @param uuid 2 or 16 octet UUID
|
||||||
*/
|
*/
|
||||||
struct bt_gatt_read_params {
|
struct bt_gatt_read_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
bt_gatt_read_func_t func;
|
bt_gatt_read_func_t func;
|
||||||
size_t handle_count;
|
size_t handle_count;
|
||||||
union {
|
union {
|
||||||
|
@ -1174,7 +1170,6 @@ typedef void (*bt_gatt_write_func_t)(struct bt_conn *conn, u8_t err,
|
||||||
|
|
||||||
/** @brief GATT Write parameters */
|
/** @brief GATT Write parameters */
|
||||||
struct bt_gatt_write_params {
|
struct bt_gatt_write_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
/** Response callback */
|
/** Response callback */
|
||||||
bt_gatt_write_func_t func;
|
bt_gatt_write_func_t func;
|
||||||
/** Attribute handle */
|
/** Attribute handle */
|
||||||
|
@ -1308,7 +1303,6 @@ enum {
|
||||||
|
|
||||||
/** @brief GATT Subscribe parameters */
|
/** @brief GATT Subscribe parameters */
|
||||||
struct bt_gatt_subscribe_params {
|
struct bt_gatt_subscribe_params {
|
||||||
struct bt_att_req _req;
|
|
||||||
bt_addr_le_t _peer;
|
bt_addr_le_t _peer;
|
||||||
/** Notification value callback */
|
/** Notification value callback */
|
||||||
bt_gatt_notify_func_t notify;
|
bt_gatt_notify_func_t notify;
|
||||||
|
|
|
@ -26,7 +26,7 @@ config BT_ATT_PREPARE_COUNT
|
||||||
|
|
||||||
config BT_ATT_TX_MAX
|
config BT_ATT_TX_MAX
|
||||||
int "Maximum number of queued outgoing ATT PDUs"
|
int "Maximum number of queued outgoing ATT PDUs"
|
||||||
default 2
|
default BT_L2CAP_TX_BUF_COUNT
|
||||||
range 1 BT_L2CAP_TX_BUF_COUNT
|
range 1 BT_L2CAP_TX_BUF_COUNT
|
||||||
help
|
help
|
||||||
Number of ATT PDUs that can be at a single moment queued for
|
Number of ATT PDUs that can be at a single moment queued for
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
|
|
||||||
#define ATT_CMD_MASK 0x40
|
#define ATT_CMD_MASK 0x40
|
||||||
|
|
||||||
#define ATT_TIMEOUT K_SECONDS(30)
|
|
||||||
|
|
||||||
typedef enum __packed {
|
typedef enum __packed {
|
||||||
ATT_COMMAND,
|
ATT_COMMAND,
|
||||||
ATT_REQUEST,
|
ATT_REQUEST,
|
||||||
|
@ -61,6 +59,9 @@ NET_BUF_POOL_DEFINE(prep_pool, CONFIG_BT_ATT_PREPARE_COUNT, BT_ATT_MTU,
|
||||||
sizeof(struct bt_attr_data), NULL);
|
sizeof(struct bt_attr_data), NULL);
|
||||||
#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
|
#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
|
||||||
|
|
||||||
|
K_MEM_SLAB_DEFINE(req_slab, sizeof(struct bt_att_req),
|
||||||
|
CONFIG_BT_ATT_TX_MAX, 16);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ATT_PENDING_RSP,
|
ATT_PENDING_RSP,
|
||||||
ATT_PENDING_CFM,
|
ATT_PENDING_CFM,
|
||||||
|
@ -100,7 +101,7 @@ static void att_req_destroy(struct bt_att_req *req)
|
||||||
req->destroy(req);
|
req->destroy(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)memset(req, 0, sizeof(*req));
|
bt_att_req_free(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bt_att *att_get(struct bt_conn *conn)
|
static struct bt_att *att_get(struct bt_conn *conn)
|
||||||
|
@ -197,7 +198,7 @@ void att_req_sent(struct bt_conn *conn, void *user_data)
|
||||||
|
|
||||||
/* Start timeout work */
|
/* Start timeout work */
|
||||||
if (att->req) {
|
if (att->req) {
|
||||||
k_delayed_work_submit(&att->timeout_work, ATT_TIMEOUT);
|
k_delayed_work_submit(&att->timeout_work, BT_ATT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
att_pdu_sent(conn, user_data);
|
att_pdu_sent(conn, user_data);
|
||||||
|
@ -343,6 +344,7 @@ static void att_process(struct bt_att *att)
|
||||||
static u8_t att_handle_rsp(struct bt_att *att, void *pdu, u16_t len, u8_t err)
|
static u8_t att_handle_rsp(struct bt_att *att, void *pdu, u16_t len, u8_t err)
|
||||||
{
|
{
|
||||||
bt_att_func_t func;
|
bt_att_func_t func;
|
||||||
|
void *params;
|
||||||
|
|
||||||
BT_DBG("err 0x%02x len %u: %s", err, len, bt_hex(pdu, len));
|
BT_DBG("err 0x%02x len %u: %s", err, len, bt_hex(pdu, len));
|
||||||
|
|
||||||
|
@ -369,16 +371,14 @@ static u8_t att_handle_rsp(struct bt_att *att, void *pdu, u16_t len, u8_t err)
|
||||||
/* Reset func so it can be reused by the callback */
|
/* Reset func so it can be reused by the callback */
|
||||||
func = att->req->func;
|
func = att->req->func;
|
||||||
att->req->func = NULL;
|
att->req->func = NULL;
|
||||||
|
params = att->req->user_data;
|
||||||
|
|
||||||
func(att->chan.chan.conn, err, pdu, len, att->req);
|
/* free allocated request so its memory can be reused */
|
||||||
|
|
||||||
/* Don't destroy if callback had reused the request */
|
|
||||||
if (!att->req->func) {
|
|
||||||
att_req_destroy(att->req);
|
att_req_destroy(att->req);
|
||||||
}
|
|
||||||
|
|
||||||
att->req = NULL;
|
att->req = NULL;
|
||||||
|
|
||||||
|
func(att->chan.chan.conn, err, pdu, len, params);
|
||||||
|
|
||||||
process:
|
process:
|
||||||
/* Process pending requests */
|
/* Process pending requests */
|
||||||
att_process(att);
|
att_process(att);
|
||||||
|
@ -2045,7 +2045,7 @@ struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op, size_t len)
|
||||||
case ATT_RESPONSE:
|
case ATT_RESPONSE:
|
||||||
case ATT_CONFIRMATION:
|
case ATT_CONFIRMATION:
|
||||||
/* Use a timeout only when responding/confirming */
|
/* Use a timeout only when responding/confirming */
|
||||||
buf = bt_l2cap_create_pdu_timeout(NULL, 0, ATT_TIMEOUT);
|
buf = bt_l2cap_create_pdu_timeout(NULL, 0, BT_ATT_TIMEOUT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||||
|
@ -2261,6 +2261,31 @@ u16_t bt_att_get_mtu(struct bt_conn *conn)
|
||||||
return att->chan.tx.mtu;
|
return att->chan.tx.mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct bt_att_req *bt_att_req_alloc(s32_t timeout)
|
||||||
|
{
|
||||||
|
struct bt_att_req *req = NULL;
|
||||||
|
|
||||||
|
/* Reserve space for request */
|
||||||
|
if (k_mem_slab_alloc(&req_slab, (void **)&req, timeout)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_DBG("req %p", req);
|
||||||
|
|
||||||
|
req->func = NULL;
|
||||||
|
req->destroy = NULL;
|
||||||
|
req->user_data = NULL;
|
||||||
|
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_att_req_free(struct bt_att_req *req)
|
||||||
|
{
|
||||||
|
BT_DBG("req %p", 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,
|
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BT_ATT_DEFAULT_LE_MTU 23
|
#define BT_ATT_DEFAULT_LE_MTU 23
|
||||||
|
#define BT_ATT_TIMEOUT K_SECONDS(30)
|
||||||
|
|
||||||
#if BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU
|
#if BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU
|
||||||
#define BT_ATT_MTU BT_L2CAP_RX_MTU
|
#define BT_ATT_MTU BT_L2CAP_RX_MTU
|
||||||
|
@ -236,19 +237,37 @@ struct bt_att_signed_write_cmd {
|
||||||
u8_t value[0];
|
u8_t value[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
void att_pdu_sent(struct bt_conn *conn, void *user_data);
|
typedef void (*bt_att_func_t)(struct bt_conn *conn, u8_t err,
|
||||||
|
const void *pdu, u16_t length,
|
||||||
|
void *user_data);
|
||||||
|
typedef void (*bt_att_destroy_t)(void *user_data);
|
||||||
|
|
||||||
void att_cfm_sent(struct bt_conn *conn, void *user_data);
|
/* ATT request context */
|
||||||
|
struct bt_att_req {
|
||||||
|
sys_snode_t node;
|
||||||
|
bt_att_func_t func;
|
||||||
|
bt_att_destroy_t destroy;
|
||||||
|
struct net_buf_simple_state state;
|
||||||
|
struct net_buf *buf;
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
bool retrying;
|
||||||
|
#endif /* CONFIG_BT_SMP */
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
void att_rsp_sent(struct bt_conn *conn, void *user_data);
|
void att_sent(struct bt_conn *conn, void *user_data);
|
||||||
|
|
||||||
void att_req_sent(struct bt_conn *conn, void *user_data);
|
|
||||||
|
|
||||||
void bt_att_init(void);
|
void bt_att_init(void);
|
||||||
u16_t bt_att_get_mtu(struct bt_conn *conn);
|
u16_t bt_att_get_mtu(struct bt_conn *conn);
|
||||||
struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op,
|
struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
|
/* Allocate a new request */
|
||||||
|
struct bt_att_req *bt_att_req_alloc(s32_t timeout);
|
||||||
|
|
||||||
|
/* Free a request */
|
||||||
|
void bt_att_req_free(struct bt_att_req *req);
|
||||||
|
|
||||||
/* Send ATT PDU over a connection */
|
/* Send ATT PDU over a connection */
|
||||||
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
|
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
|
@ -1602,13 +1602,23 @@ static int gatt_send(struct bt_conn *conn, struct net_buf *buf,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
struct bt_att_req *req = params;
|
struct bt_att_req *req;
|
||||||
|
|
||||||
|
/* Allocate new request */
|
||||||
|
req = bt_att_req_alloc(BT_ATT_TIMEOUT);
|
||||||
|
if (!req) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
req->buf = buf;
|
req->buf = buf;
|
||||||
req->func = func;
|
req->func = func;
|
||||||
req->destroy = destroy;
|
req->destroy = destroy;
|
||||||
|
req->user_data = params;
|
||||||
|
|
||||||
err = bt_att_req_send(conn, req);
|
err = bt_att_req_send(conn, req);
|
||||||
|
if (err) {
|
||||||
|
bt_att_req_free(req);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = bt_att_send(conn, buf, NULL, NULL);
|
err = bt_att_send(conn, buf, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue