diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index 1a59f341038..957abf0a0e3 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -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; diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 8cb345481ab..f86a6cb2aac 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -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; } diff --git a/subsys/bluetooth/host/att_internal.h b/subsys/bluetooth/host/att_internal.h index b8cd5d0a903..1fc437b9af6 100644 --- a/subsys/bluetooth/host/att_internal.h +++ b/subsys/bluetooth/host/att_internal.h @@ -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); diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index afaa6513481..002726addfc 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -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,