diff --git a/android/gatt.c b/android/gatt.c
index 429181f..f450eac 100644
--- a/android/gatt.c
+++ b/android/gatt.c
/* Valid for client applications */
struct queue *notifications;
-
- /* Transaction data valid for server application */
- struct pending_trans_data trans_id;
};
struct element_id {
struct app_connection {
struct gatt_device *device;
struct gatt_app *app;
+ struct queue *transactions;
int32_t id;
};
connection_cleanup(conn->device);
cleanup:
+ queue_destroy(conn->transactions, free);
device_unref(conn->device);
free(conn);
}
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;
}
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) {
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,
{
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);
}
/* 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)
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;
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("");
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;