Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/4] android/gatt: Fix parallel reading/writing attributes values from applications
@ 2014-05-30  5:51 Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 2/4] shared/gatt: Add function to check if handle was found in database Marcin Kraglak
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-05-30  5:51 UTC (permalink / raw)
  To: linux-bluetooth

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.
---
 android/gatt.c | 85 ++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 59 insertions(+), 26 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 66d6224..80d9f30 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -106,9 +106,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 {
@@ -175,6 +172,7 @@ struct gatt_device {
 struct app_connection {
 	struct gatt_device *device;
 	struct gatt_app *app;
+	struct queue *transactions;
 	int32_t id;
 };
 
@@ -182,6 +180,7 @@ static struct ipc *hal_ipc = NULL;
 static bdaddr_t adapter_addr;
 static bool scanning = false;
 static unsigned int advertising_cnt = 0;
+static int32_t trans_id = 1;
 
 static struct queue *gatt_apps = NULL;
 static struct queue *gatt_devices = NULL;
@@ -855,6 +854,8 @@ static void destroy_connection(void *data)
 	if (conn->device->conn_cnt == 0)
 		connection_cleanup(conn->device);
 
+	queue_destroy(conn->transactions, free);
+
 cleanup:
 	device_unref(conn->device);
 	free(conn);
@@ -1305,6 +1306,12 @@ 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!?");
 
@@ -4169,26 +4176,29 @@ 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 *new_transaction(unsigned int id,
+								uint8_t opcode)
 {
-	app->trans_id.id = id;
-	app->trans_id.opcode = opcode;
-}
+	struct pending_trans_data *transaction;
 
-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;
+
+	transaction->id = 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) {
@@ -4205,14 +4215,23 @@ 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 = new_transaction(trans_id++, att_opcode);
+	if (!transaction) {
+		error("gatt: failed to allocate memory for transaction");
+		goto failed;
+	}
+
+	if (!queue_push_tail(conn->transactions, transaction)) {
+		free(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,
@@ -4232,9 +4251,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);
@@ -4250,7 +4269,16 @@ 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 = new_transaction(trans_id++, att_opcode);
+	if (!transaction) {
+		error("gatt: failed to allocate memory for transaction");
+		goto failed;
+	}
+
+	if (!queue_push_tail(conn->transactions, transaction)) {
+		free(transaction);
+		goto failed;
+	}
 
 	/* TODO figure it out */
 	if (att_opcode == ATT_OP_EXEC_WRITE_REQ)
@@ -4263,7 +4291,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;
@@ -4557,11 +4585,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("");
@@ -4573,22 +4608,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;
 
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] shared/gatt: Add function to check if handle was found in database
  2014-05-30  5:51 [PATCH 1/4] android/gatt: Fix parallel reading/writing attributes values from applications Marcin Kraglak
@ 2014-05-30  5:51 ` Marcin Kraglak
  2014-05-30  8:32   ` Luiz Augusto von Dentz
  2014-05-30  5:51 ` [PATCH 3/4] android/gatt: Chack if given handle exists " Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 4/4] android/gatt: Check for invalid handle errors Marcin Kraglak
  2 siblings, 1 reply; 6+ messages in thread
From: Marcin Kraglak @ 2014-05-30  5:51 UTC (permalink / raw)
  To: linux-bluetooth

It will return true if attribute with given handle exists in db, otherwise
false.
---
 src/shared/gatt-db.c | 18 ++++++++++++++++++
 src/shared/gatt-db.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 998e93e..de1de57 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -758,3 +758,21 @@ uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle)
 
 	return attribute->permissions;
 }
+
+bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle)
+{
+	struct gatt_db_attribute *attribute;
+	struct gatt_db_service *service;
+	uint16_t service_handle;
+
+	service = queue_find(db->services, find_service_for_handle,
+							INT_TO_PTR(handle));
+	if (!service)
+		return false;
+
+	service_handle = service->attributes[0]->handle;
+
+	attribute = service->attributes[handle - service_handle];
+
+	return attribute ? true : false;
+}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index f2f2f4d..ca36d32 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -93,3 +93,4 @@ const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
 uint16_t gatt_db_get_end_handle(struct gatt_db *db, uint16_t handle);
 
 uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle);
+bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle);
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] android/gatt: Chack if given handle exists in database
  2014-05-30  5:51 [PATCH 1/4] android/gatt: Fix parallel reading/writing attributes values from applications Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 2/4] shared/gatt: Add function to check if handle was found in database Marcin Kraglak
@ 2014-05-30  5:51 ` Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 4/4] android/gatt: Check for invalid handle errors Marcin Kraglak
  2 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-05-30  5:51 UTC (permalink / raw)
  To: linux-bluetooth

If attribute doesn't exist, we should return ATT_ECODE_ATTR_NOT_FOUND
error.
---
 android/gatt.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/android/gatt.c b/android/gatt.c
index 80d9f30..48a32ec 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -4070,6 +4070,9 @@ static void read_requested_attributes(void *data, void *user_data)
 	uint8_t *value;
 	int value_len;
 
+	if (!gatt_db_has_attribute(gatt_db, resp_data->handle))
+		return;
+
 	permissions = gatt_db_get_attribute_permissions(gatt_db,
 							resp_data->handle);
 
@@ -5067,6 +5070,9 @@ static void write_cmd_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return;
 
+	if (!gatt_db_has_attribute(gatt_db, handle))
+		return;
+
 	permissions = gatt_db_get_attribute_permissions(gatt_db, handle);
 	if (check_device_permissions(dev, cmd[0], permissions))
 		return;
@@ -5093,6 +5099,9 @@ static void write_signed_cmd_request(const uint8_t *cmd, uint16_t cmd_len,
 
 	len = dec_signed_write_cmd(cmd, cmd_len, &handle, value, &vlen, s);
 
+	if (!gatt_db_has_attribute(gatt_db, handle))
+		return;
+
 	permissions = gatt_db_get_attribute_permissions(gatt_db, handle);
 	if (check_device_permissions(dev, cmd[0], permissions))
 		return;
@@ -5133,6 +5142,9 @@ static uint8_t write_req_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (!gatt_db_has_attribute(gatt_db, handle))
+		return ATT_ECODE_ATTR_NOT_FOUND;
+
 	permissions = gatt_db_get_attribute_permissions(gatt_db, handle);
 
 	error = check_device_permissions(dev, cmd[0], permissions);
@@ -5181,6 +5193,9 @@ static uint8_t write_prep_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (!gatt_db_has_attribute(gatt_db, handle))
+		return ATT_ECODE_ATTR_NOT_FOUND;
+
 	permissions = gatt_db_get_attribute_permissions(gatt_db, handle);
 
 	error = check_device_permissions(dev, cmd[0], permissions);
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] android/gatt: Check for invalid handle errors
  2014-05-30  5:51 [PATCH 1/4] android/gatt: Fix parallel reading/writing attributes values from applications Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 2/4] shared/gatt: Add function to check if handle was found in database Marcin Kraglak
  2014-05-30  5:51 ` [PATCH 3/4] android/gatt: Chack if given handle exists " Marcin Kraglak
@ 2014-05-30  5:51 ` Marcin Kraglak
  2 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-05-30  5:51 UTC (permalink / raw)
  To: linux-bluetooth

Check if handle or range is valid for server.
---
 android/gatt.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/android/gatt.c b/android/gatt.c
index 48a32ec..8ccbad9 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -4753,6 +4753,9 @@ static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (start > end || start == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	q = queue_new();
 	if (!q)
 		return ATT_ECODE_INSUFF_RESOURCES;
@@ -4806,7 +4809,7 @@ static uint8_t read_by_type(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
-	if (start > end)
+	if (start > end || start == 0)
 		return ATT_ECODE_INVALID_HANDLE;
 
 	q = queue_new();
@@ -4869,6 +4872,9 @@ static uint8_t read_request(const uint8_t *cmd, uint16_t cmd_len,
 		return ATT_ECODE_REQ_NOT_SUPP;
 	}
 
+	if (handle == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	data = new0(struct pending_request, 1);
 	if (!data)
 		return ATT_ECODE_INSUFF_RESOURCES;
@@ -4948,6 +4954,9 @@ static uint8_t find_info_handle(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (start > end || start == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	q = queue_new();
 	if (!q)
 		return ATT_ECODE_UNLIKELY;
@@ -5017,6 +5026,9 @@ static uint8_t find_by_type_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (start > end || start == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	q = queue_new();
 	if (!q)
 		return ATT_ECODE_UNLIKELY;
@@ -5070,6 +5082,9 @@ static void write_cmd_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return;
 
+	if (handle == 0)
+		return;
+
 	if (!gatt_db_has_attribute(gatt_db, handle))
 		return;
 
@@ -5099,6 +5114,9 @@ static void write_signed_cmd_request(const uint8_t *cmd, uint16_t cmd_len,
 
 	len = dec_signed_write_cmd(cmd, cmd_len, &handle, value, &vlen, s);
 
+	if (handle == 0)
+		return;
+
 	if (!gatt_db_has_attribute(gatt_db, handle))
 		return;
 
@@ -5142,6 +5160,9 @@ static uint8_t write_req_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (handle == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	if (!gatt_db_has_attribute(gatt_db, handle))
 		return ATT_ECODE_ATTR_NOT_FOUND;
 
@@ -5193,6 +5214,9 @@ static uint8_t write_prep_request(const uint8_t *cmd, uint16_t cmd_len,
 	if (!len)
 		return ATT_ECODE_INVALID_PDU;
 
+	if (handle == 0)
+		return ATT_ECODE_INVALID_HANDLE;
+
 	if (!gatt_db_has_attribute(gatt_db, handle))
 		return ATT_ECODE_ATTR_NOT_FOUND;
 
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/4] shared/gatt: Add function to check if handle was found in database
  2014-05-30  5:51 ` [PATCH 2/4] shared/gatt: Add function to check if handle was found in database Marcin Kraglak
@ 2014-05-30  8:32   ` Luiz Augusto von Dentz
  2014-05-30  9:16     ` Szymon Janc
  0 siblings, 1 reply; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-05-30  8:32 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth@vger.kernel.org

Hi Marcin,

On Fri, May 30, 2014 at 8:51 AM, Marcin Kraglak
<marcin.kraglak@tieto.com> wrote:
> It will return true if attribute with given handle exists in db, otherwise
> false.
> ---
>  src/shared/gatt-db.c | 18 ++++++++++++++++++
>  src/shared/gatt-db.h |  1 +
>  2 files changed, 19 insertions(+)
>
> diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
> index 998e93e..de1de57 100644
> --- a/src/shared/gatt-db.c
> +++ b/src/shared/gatt-db.c
> @@ -758,3 +758,21 @@ uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle)
>
>         return attribute->permissions;
>  }
> +
> +bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle)
> +{
> +       struct gatt_db_attribute *attribute;
> +       struct gatt_db_service *service;
> +       uint16_t service_handle;
> +
> +       service = queue_find(db->services, find_service_for_handle,
> +                                                       INT_TO_PTR(handle));
> +       if (!service)
> +               return false;
> +
> +       service_handle = service->attributes[0]->handle;
> +
> +       attribute = service->attributes[handle - service_handle];
> +
> +       return attribute ? true : false;
> +}
> diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
> index f2f2f4d..ca36d32 100644
> --- a/src/shared/gatt-db.h
> +++ b/src/shared/gatt-db.h
> @@ -93,3 +93,4 @@ const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
>  uint16_t gatt_db_get_end_handle(struct gatt_db *db, uint16_t handle);
>
>  uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle);
> +bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle);
> --
> 1.9.0

This kind of API design is inefficient since it normally gonna cause
double lookup and in any case gatt_db_get_attribute_permissions needs
a fix since right now it cannot really tell if an error happen.
Perhaps we could change the return to int and have another parameter
to hold the permissions value or we can create an API for attribute
themselves e.g. gatt_db_get_attribute + gatt_attribute_get_permission.


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/4] shared/gatt: Add function to check if handle was found in database
  2014-05-30  8:32   ` Luiz Augusto von Dentz
@ 2014-05-30  9:16     ` Szymon Janc
  0 siblings, 0 replies; 6+ messages in thread
From: Szymon Janc @ 2014-05-30  9:16 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Marcin Kraglak, linux-bluetooth@vger.kernel.org

Hi Luiz,

On Friday 30 of May 2014 11:32:34 Luiz Augusto von Dentz wrote:
> Hi Marcin,
> 
> On Fri, May 30, 2014 at 8:51 AM, Marcin Kraglak
> <marcin.kraglak@tieto.com> wrote:
> > It will return true if attribute with given handle exists in db, otherwise
> > false.
> > ---
> >  src/shared/gatt-db.c | 18 ++++++++++++++++++
> >  src/shared/gatt-db.h |  1 +
> >  2 files changed, 19 insertions(+)
> >
> > diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
> > index 998e93e..de1de57 100644
> > --- a/src/shared/gatt-db.c
> > +++ b/src/shared/gatt-db.c
> > @@ -758,3 +758,21 @@ uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle)
> >
> >         return attribute->permissions;
> >  }
> > +
> > +bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle)
> > +{
> > +       struct gatt_db_attribute *attribute;
> > +       struct gatt_db_service *service;
> > +       uint16_t service_handle;
> > +
> > +       service = queue_find(db->services, find_service_for_handle,
> > +                                                       INT_TO_PTR(handle));
> > +       if (!service)
> > +               return false;
> > +
> > +       service_handle = service->attributes[0]->handle;
> > +
> > +       attribute = service->attributes[handle - service_handle];
> > +
> > +       return attribute ? true : false;
> > +}
> > diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
> > index f2f2f4d..ca36d32 100644
> > --- a/src/shared/gatt-db.h
> > +++ b/src/shared/gatt-db.h
> > @@ -93,3 +93,4 @@ const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
> >  uint16_t gatt_db_get_end_handle(struct gatt_db *db, uint16_t handle);
> >
> >  uint32_t gatt_db_get_attribute_permissions(struct gatt_db *db, uint16_t handle);
> > +bool gatt_db_has_attribute(struct gatt_db *db, uint16_t handle);
> > --
> > 1.9.0
> 
> This kind of API design is inefficient since it normally gonna cause
> double lookup and in any case gatt_db_get_attribute_permissions needs
> a fix since right now it cannot really tell if an error happen.
> Perhaps we could change the return to int and have another parameter
> to hold the permissions value or we can create an API for attribute
> themselves e.g. gatt_db_get_attribute + gatt_attribute_get_permission.
> 

For now I think we can fix only gatt_db_get_attribute_permissions() as you
suggested. But I agree that on long run having attribute API would be nice.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-05-30  9:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-30  5:51 [PATCH 1/4] android/gatt: Fix parallel reading/writing attributes values from applications Marcin Kraglak
2014-05-30  5:51 ` [PATCH 2/4] shared/gatt: Add function to check if handle was found in database Marcin Kraglak
2014-05-30  8:32   ` Luiz Augusto von Dentz
2014-05-30  9:16     ` Szymon Janc
2014-05-30  5:51 ` [PATCH 3/4] android/gatt: Chack if given handle exists " Marcin Kraglak
2014-05-30  5:51 ` [PATCH 4/4] android/gatt: Check for invalid handle errors Marcin Kraglak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox