From: Szymon Janc <szymon.janc@tieto.com>
To: Marcin Kraglak <marcin.kraglak@tieto.com>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH 1/3] android/gatt: Fix parallel reading/writing attributes values from applications
Date: Fri, 06 Jun 2014 06:08:17 +0200 [thread overview]
Message-ID: <7307660.f9KvX5gET3@leonov> (raw)
In-Reply-To: <1401961132-29459-1-git-send-email-marcin.kraglak@tieto.com>
Hi Marcin,
On Thursday 05 of June 2014 11:38:50 Marcin Kraglak wrote:
> It is needed because in some cases we send few read requests to
> applications. Now all transactions data are overriden by last one, and if
> application wants to respond to previous requests, transaction data is not
> found.
> It happens when two devices will read attribute from one application in the
> same time or if device will read few values in time (i.e. read by type
> request or find by type value request).
> ---
> android/gatt.c | 77
> ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed,
> 50 insertions(+), 27 deletions(-)
>
> 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;
All patches applied, thanks.
--
BR
Szymon Janc
prev parent reply other threads:[~2014-06-06 4:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-05 9:38 [PATCH 1/3] android/gatt: Fix parallel reading/writing attributes values from applications Marcin Kraglak
2014-06-05 9:38 ` [PATCH 2/3] android/gatt: Fix state of pending request for prep write Marcin Kraglak
2014-06-05 9:38 ` [PATCH 3/3] android/gatt: Handle prepare and execute write Marcin Kraglak
2014-06-06 4:08 ` Szymon Janc [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7307660.f9KvX5gET3@leonov \
--to=szymon.janc@tieto.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=marcin.kraglak@tieto.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox