Diff between 2fbdb09de784fa0f2f1c4b8103c7c3e14a29b015 and a94d2065b6123e522509d235fbfc9f2d162524cb

Changed Files

File Additions Deletions Status
android/gatt.c +50 -27 modified

Full Patch

diff --git a/android/gatt.c b/android/gatt.c
index 429181f..f450eac 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -105,9 +105,6 @@ struct gatt_app {
 
 	/* Valid for client applications */
 	struct queue *notifications;
-
-	/* Transaction data valid for server application */
-	struct pending_trans_data trans_id;
 };
 
 struct element_id {
@@ -174,6 +171,7 @@ struct gatt_device {
 struct app_connection {
 	struct gatt_device *device;
 	struct gatt_app *app;
+	struct queue *transactions;
 	int32_t id;
 };
 
@@ -855,6 +853,7 @@ static void destroy_connection(void *data)
 		connection_cleanup(conn->device);
 
 cleanup:
+	queue_destroy(conn->transactions, free);
 	device_unref(conn->device);
 	free(conn);
 }
@@ -1304,9 +1303,15 @@ static struct app_connection *create_connection(struct gatt_device *device,
 	new_conn->app = app;
 	new_conn->id = last_conn_id++;
 
+	new_conn->transactions = queue_new();
+	if (!new_conn->transactions) {
+		free(new_conn);
+		return NULL;
+	}
+
 	if (!queue_push_head(app_connections, new_conn)) {
 		error("gatt: Cannot push client on the client queue!?");
-
+		queue_destroy(new_conn->transactions, free);
 		free(new_conn);
 		return NULL;
 	}
@@ -4167,26 +4172,35 @@ done:
 		send_dev_pending_response(dev, opcode);
 }
 
-static void set_trans_id(struct gatt_app *app, unsigned int id, int8_t opcode)
+static struct pending_trans_data *conn_add_transact(struct app_connection *conn,
+								uint8_t opcode)
 {
-	app->trans_id.id = id;
-	app->trans_id.opcode = opcode;
-}
+	struct pending_trans_data *transaction;
+	static int32_t trans_id = 1;
 
-static void clear_trans_id(struct gatt_app *app)
-{
-	app->trans_id.id = 0;
-	app->trans_id.opcode = 0;
+	transaction = new0(struct pending_trans_data, 1);
+	if (!transaction)
+		return NULL;
+
+	if (!queue_push_tail(conn->transactions, transaction)) {
+		free(transaction);
+		return NULL;
+	}
+
+	transaction->id = trans_id++;
+	transaction->opcode = opcode;
+
+	return transaction;
 }
 
 static void read_cb(uint16_t handle, uint16_t offset, uint8_t att_opcode,
 					bdaddr_t *bdaddr, void *user_data)
 {
+	struct pending_trans_data *transaction;
 	struct hal_ev_gatt_server_request_read ev;
 	struct gatt_app *app;
 	struct app_connection *conn;
 	int32_t id = PTR_TO_INT(user_data);
-	static int32_t trans_id = 1;
 
 	app = find_app_by_id(id);
 	if (!app) {
@@ -4203,14 +4217,16 @@ static void read_cb(uint16_t handle, uint16_t offset, uint8_t att_opcode,
 	memset(&ev, 0, sizeof(ev));
 
 	/* Store the request data, complete callback and transaction id */
-	set_trans_id(app, trans_id++, att_opcode);
+	transaction = conn_add_transact(conn, att_opcode);
+	if (!transaction)
+		goto failed;
 
 	bdaddr2android(bdaddr, ev.bdaddr);
 	ev.conn_id = conn->id;
 	ev.attr_handle = handle;
 	ev.offset = offset;
 	ev.is_long = att_opcode == ATT_OP_READ_BLOB_REQ;
-	ev.trans_id = app->trans_id.id;
+	ev.trans_id = transaction->id;
 
 	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
 					HAL_EV_GATT_SERVER_REQUEST_READ,
@@ -4230,9 +4246,9 @@ static void write_cb(uint16_t handle, uint16_t offset,
 {
 	uint8_t buf[IPC_MTU];
 	struct hal_ev_gatt_server_request_write *ev = (void *) buf;
+	struct pending_trans_data *transaction;
 	struct gatt_app *app;
 	int32_t id = PTR_TO_INT(user_data);
-	static int32_t trans_id = 1;
 	struct app_connection *conn;
 
 	app = find_app_by_id(id);
@@ -4248,7 +4264,9 @@ static void write_cb(uint16_t handle, uint16_t offset,
 	}
 
 	/* Store the request data, complete callback and transaction id */
-	set_trans_id(app, trans_id++, att_opcode);
+	transaction = conn_add_transact(conn, att_opcode);
+	if (!transaction)
+		goto failed;
 
 	/* TODO figure it out */
 	if (att_opcode == ATT_OP_EXEC_WRITE_REQ)
@@ -4261,7 +4279,7 @@ static void write_cb(uint16_t handle, uint16_t offset,
 	ev->offset = offset;
 
 	ev->conn_id = conn->id;
-	ev->trans_id = app->trans_id.id;
+	ev->trans_id = transaction->id;
 
 	ev->is_prep = att_opcode == ATT_OP_PREP_WRITE_REQ;
 	ev->need_rsp = att_opcode == ATT_OP_WRITE_REQ;
@@ -4555,11 +4573,18 @@ reply:
 				HAL_OP_GATT_SERVER_SEND_INDICATION, status);
 }
 
+static bool match_trans_id(const void *data, const void *user_data)
+{
+	const struct pending_trans_data *transaction = data;
+
+	return transaction->id == PTR_TO_UINT(user_data);
+}
+
 static void handle_server_send_response(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_server_send_response *cmd = buf;
+	struct pending_trans_data *transaction;
 	struct app_connection *conn;
-	struct gatt_app *app;
 	uint8_t status;
 
 	DBG("");
@@ -4571,22 +4596,20 @@ static void handle_server_send_response(const void *buf, uint16_t len)
 		goto reply;
 	}
 
-	app = conn->app;
-
-	if ((unsigned int)cmd->trans_id != app->trans_id.id) {
-		error("gatt: transaction ID mismatch (%d!=%d)",
-					cmd->trans_id, app->trans_id.id);
-
+	transaction = queue_remove_if(conn->transactions, match_trans_id,
+						UINT_TO_PTR(cmd->trans_id));
+	if (!transaction) {
+		error("gatt: transaction ID = %d not found", cmd->trans_id);
 		status = HAL_STATUS_FAILED;
 		goto reply;
 	}
 
-	send_gatt_response(conn->app->trans_id.opcode, cmd->handle, cmd->offset,
+	send_gatt_response(transaction->opcode, cmd->handle, cmd->offset,
 					cmd->status, cmd->len, cmd->data,
 					&conn->device->bdaddr);
 
 	/* Clean request data */
-	clear_trans_id(app);
+	free(transaction);
 
 	status = HAL_STATUS_SUCCESS;