diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 17e15b1..2ca318a 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
unsigned int read_id;
unsigned int read_blob_id;
unsigned int prep_write_id;
+ unsigned int exec_write_id;
struct queue *prep_queue;
unsigned int max_prep_queue_len;
bt_att_unregister(server->att, server->read_id);
bt_att_unregister(server->att, server->read_blob_id);
bt_att_unregister(server->att, server->prep_write_id);
+ bt_att_unregister(server->att, server->exec_write_id);
if (server->pending_read_op)
server->pending_read_op->server = NULL;
NULL);
}
+static void exec_next_prep_write(struct bt_gatt_server *server,
+ uint16_t ehandle, uint8_t att_ecode);
+
+static void exec_write_complete_cb(struct gatt_db_attribute *attr, int err,
+ void *user_data)
+{
+ struct bt_gatt_server *server = user_data;
+ uint16_t handle = gatt_db_attribute_get_handle(attr);
+ uint16_t att_ecode = att_ecode_from_error(err);
+
+ exec_next_prep_write(server, handle, att_ecode);
+}
+
+static void exec_next_prep_write(struct bt_gatt_server *server,
+ uint16_t ehandle, uint8_t att_ecode)
+{
+ struct prep_write_data *next = NULL;
+ uint8_t rsp_opcode = BT_ATT_OP_EXEC_WRITE_RSP;
+ uint8_t error_pdu[4];
+ uint8_t *rsp_pdu = NULL;
+ uint16_t rsp_len = 0;
+ struct gatt_db_attribute *attr;
+ bool status;
+
+ if (att_ecode)
+ goto error;
+
+ next = queue_pop_head(server->prep_queue);
+ if (!next)
+ goto done;
+
+ attr = gatt_db_get_attribute(server->db, next->handle);
+ if (!attr) {
+ att_ecode = BT_ATT_ERROR_UNLIKELY;
+ goto error;
+ }
+
+ status = gatt_db_attribute_write(attr, next->offset,
+ next->value, next->length,
+ BT_ATT_OP_EXEC_WRITE_REQ, NULL,
+ exec_write_complete_cb, server);
+
+ prep_write_data_destroy(next);
+
+ if (status)
+ return;
+
+ att_ecode = BT_ATT_ERROR_UNLIKELY;
+
+error:
+ rsp_opcode = BT_ATT_OP_ERROR_RSP;
+ rsp_len = 4;
+ rsp_pdu = error_pdu;
+ encode_error_rsp(BT_ATT_OP_EXEC_WRITE_REQ, ehandle, att_ecode, rsp_pdu);
+
+done:
+ bt_att_send(server->att, rsp_opcode, rsp_pdu, rsp_len, NULL, NULL,
+ NULL);
+}
+
+static void exec_write_cb(uint8_t opcode, const void *pdu,
+ uint16_t length, void *user_data)
+{
+ struct bt_gatt_server *server = user_data;
+ uint8_t flags;
+ uint8_t ecode;
+ uint8_t rsp_opcode;
+ uint8_t error_pdu[4];
+ uint8_t *rsp_pdu = NULL;
+ uint16_t rsp_len = 0;
+ bool write;
+
+ if (length != 1) {
+ ecode = BT_ATT_ERROR_INVALID_PDU;
+ goto error;
+ }
+
+ flags = ((uint8_t *) pdu)[0];
+
+ util_debug(server->debug_callback, server->debug_data,
+ "Exec Write Req - flags: 0x%02x", flags);
+
+ if (flags == 0x00)
+ write = false;
+ else if (flags == 0x01)
+ write = true;
+ else {
+ ecode = BT_ATT_ERROR_INVALID_PDU;
+ goto error;
+ }
+
+ if (!write) {
+ queue_remove_all(server->prep_queue, NULL, NULL,
+ prep_write_data_destroy);
+ rsp_opcode = BT_ATT_OP_EXEC_WRITE_RSP;
+ goto done;
+ }
+
+ exec_next_prep_write(server, 0, 0);
+
+ return;
+
+error:
+ rsp_opcode = BT_ATT_OP_ERROR_RSP;
+ rsp_len = 4;
+ rsp_pdu = error_pdu;
+ encode_error_rsp(opcode, 0, ecode, rsp_pdu);
+
+done:
+ bt_att_send(server->att, rsp_opcode, rsp_pdu, rsp_len, NULL, NULL,
+ NULL);
+}
+
static void exchange_mtu_cb(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
if (!server->prep_write_id)
return false;
+ /* Execute Write Request */
+ server->exec_write_id = bt_att_register(server->att,
+ BT_ATT_OP_EXEC_WRITE_REQ,
+ exec_write_cb, server, NULL);
+ if (!server->exec_write_id)
+ return NULL;
+
return true;
}