Bluetooth: GATT: Add bt_gatt_write_response_cb

This adds bt_gatt_write_response_cb works similarly to
bt_gatt_notify_cb which can take a callback to be called when the PDU
is considered transmitted over the air.

Note: This can also be used to disable the ATT flow control which would
blocks sending multiple commands without wainting their transmissions.

Fixes #11558

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2019-01-14 10:55:33 -03:00 committed by Anas Nashif
commit a779705f16
4 changed files with 53 additions and 23 deletions

View file

@ -697,7 +697,7 @@ ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn,
*
* @param conn Connection object.
*/
typedef void (*bt_gatt_notify_complete_func_t) (struct bt_conn *conn);
typedef void (*bt_gatt_complete_func_t) (struct bt_conn *conn);
/** @brief Notify attribute value change with callback.
*
@ -713,7 +713,7 @@ typedef void (*bt_gatt_notify_complete_func_t) (struct bt_conn *conn);
*/
int bt_gatt_notify_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *data, u16_t len,
bt_gatt_notify_complete_func_t func);
bt_gatt_complete_func_t func);
/** @brief Notify attribute value change.
*
@ -999,6 +999,30 @@ struct bt_gatt_write_params {
*/
int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params);
/** @brief Write Attribute Value by handle without response with callback.
*
* This function works in the same way as @ref bt_gatt_write_without_response.
* With the addition that after sending the write the callback function will be
* called.
*
* Note: By using a callback it also disable the internal flow control
* which would prevent sending multiple commands without wainting their
* transmissions to complete, so if that is required the caller shall not
* submit more data until the callback is called.
*
* @param conn Connection object.
* @param handle Attribute handle.
* @param data Data to be written.
* @param length Data length.
* @param sign Whether to sign data
* @param func Transmission complete callback.
*
* @return 0 in case of success or negative value in case of error.
*/
int bt_gatt_write_without_response_cb(struct bt_conn *conn, u16_t handle,
const void *data, u16_t length,
bool sign, bt_gatt_complete_func_t func);
/** @brief Write Attribute Value by handle without response
*
* This procedure write the attribute value without requiring an
@ -1012,9 +1036,13 @@ int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params);
*
* @return 0 in case of success or negative value in case of error.
*/
int bt_gatt_write_without_response(struct bt_conn *conn, u16_t handle,
const void *data, u16_t length,
bool sign);
static inline int bt_gatt_write_without_response(struct bt_conn *conn,
u16_t handle, const void *data,
u16_t length, bool sign)
{
return bt_gatt_write_without_response_cb(conn, handle, data, length,
sign, NULL);
}
struct bt_gatt_subscribe_params;

View file

@ -2191,7 +2191,7 @@ u16_t bt_att_get_mtu(struct bt_conn *conn)
return att->chan.tx.mtu;
}
int bt_att_send(struct bt_conn *conn, struct net_buf *buf)
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb)
{
struct bt_att *att;
struct bt_att_hdr *hdr;
@ -2205,11 +2205,14 @@ int bt_att_send(struct bt_conn *conn, struct net_buf *buf)
return -ENOTCONN;
}
k_sem_take(&att->tx_sem, K_FOREVER);
if (!att_is_connected(att)) {
BT_WARN("Disconnected");
k_sem_give(&att->tx_sem);
return -ENOTCONN;
/* Don't use tx_sem if caller has set it own callback */
if (!cb) {
k_sem_take(&att->tx_sem, K_FOREVER);
if (!att_is_connected(att)) {
BT_WARN("Disconnected");
k_sem_give(&att->tx_sem);
return -ENOTCONN;
}
}
hdr = (void *)buf->data;
@ -2227,7 +2230,7 @@ int bt_att_send(struct bt_conn *conn, struct net_buf *buf)
}
}
bt_l2cap_send_cb(conn, BT_L2CAP_CID_ATT, buf, att_cb(buf));
bt_l2cap_send_cb(conn, BT_L2CAP_CID_ATT, buf, cb ? cb : att_cb(buf));
return 0;
}

View file

@ -242,7 +242,7 @@ struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op,
size_t len);
/* Send ATT PDU over a connection */
int bt_att_send(struct bt_conn *conn, struct net_buf *buf);
int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb);
/* Send ATT Request over a connection */
int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req);

View file

@ -774,14 +774,14 @@ struct notify_data {
int err;
u16_t type;
const struct bt_gatt_attr *attr;
bt_gatt_notify_complete_func_t func;
bt_gatt_complete_func_t func;
const void *data;
u16_t len;
struct bt_gatt_indicate_params *params;
};
static int gatt_notify(struct bt_conn *conn, u16_t handle, const void *data,
size_t len, bt_gatt_notify_complete_func_t cb)
size_t len, bt_gatt_complete_func_t cb)
{
struct net_buf *buf;
struct bt_att_notify *nfy;
@ -800,9 +800,7 @@ static int gatt_notify(struct bt_conn *conn, u16_t handle, const void *data,
net_buf_add(buf, len);
memcpy(nfy->value, data, len);
bt_l2cap_send_cb(conn, BT_L2CAP_CID_ATT, buf, cb);
return 0;
return bt_att_send(conn, buf, cb);
}
static void gatt_indicate_rsp(struct bt_conn *conn, u8_t err,
@ -828,7 +826,7 @@ static int gatt_send(struct bt_conn *conn, struct net_buf *buf,
err = bt_att_req_send(conn, req);
} else {
err = bt_att_send(conn, buf);
err = bt_att_send(conn, buf, NULL);
}
if (err) {
@ -977,7 +975,7 @@ static u8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data)
int bt_gatt_notify_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *data, u16_t len,
bt_gatt_notify_complete_func_t func)
bt_gatt_complete_func_t func)
{
struct notify_data nfy;
@ -2089,8 +2087,9 @@ static void gatt_write_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
params->func(conn, err, params);
}
int bt_gatt_write_without_response(struct bt_conn *conn, u16_t handle,
const void *data, u16_t length, bool sign)
int bt_gatt_write_without_response_cb(struct bt_conn *conn, u16_t handle,
const void *data, u16_t length, bool sign,
bt_gatt_complete_func_t func)
{
struct net_buf *buf;
struct bt_att_write_cmd *cmd;
@ -2127,7 +2126,7 @@ int bt_gatt_write_without_response(struct bt_conn *conn, u16_t handle,
BT_DBG("handle 0x%04x length %u", handle, length);
return gatt_send(conn, buf, NULL, NULL, NULL);
return bt_att_send(conn, buf, func);
}
static int gatt_exec_write(struct bt_conn *conn,