[PATCH BlueZ 09/11] shared/gatt-server: Implement "Execute Write" request.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for handling ATT "Execute Write" requests for
the server role.
---
 src/shared/gatt-server.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 48a55e7..3a247d9 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -88,6 +88,7 @@ struct bt_gatt_server {
 	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;
@@ -114,6 +115,7 @@ static void bt_gatt_server_free(struct bt_gatt_server *server)
 	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;
@@ -1039,6 +1041,116 @@ done:
 									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];
+
+	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)
 {
@@ -1139,6 +1251,13 @@ static bool gatt_server_register_att_handlers(struct bt_gatt_server *server)
 	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;
 }
 
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux