2014-04-12 22:00:21

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 00/10] android/gatt: GATT Client write types support

This patch set adds support for different write types.
For this I had to expose some additional API from attrib.

Only signed write left to implement.

This patch set also do some code cleaning.

Lukasz Rymanowski (10):
attrib: Add API for reliable write
attrib: Expose write execute
android/gatt: Add helper to create descr_data
android/gatt: Avoid double helper struct for read/write characteristic
android/gatt: Add helper to create characteristic op data
android/gatt: Fix error msg
android/gatt: Daemon accepts only default write type
android/gatt: Add support for reliable write
android/gatt: Add support for write execute
android/gatt: Add support for write without response

android/gatt.c | 264 ++++++++++++++++++++++++++++++++++++++++++---------------
attrib/gatt.c | 24 ++++++
attrib/gatt.h | 8 ++
3 files changed, 226 insertions(+), 70 deletions(-)

--
1.8.4



2014-04-14 14:28:07

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 01/10] attrib: Add API for reliable write

Hi Łukasz,

On Sunday 13 of April 2014 00:00:22 Lukasz Rymanowski wrote:
> Android expose to application api for reliable write. Therefore we need
> to add this support to gattrib
> ---
> attrib/gatt.c | 18 ++++++++++++++++++
> attrib/gatt.h | 6 ++++++
> 2 files changed, 24 insertions(+)
>
> diff --git a/attrib/gatt.c b/attrib/gatt.c
> index 49cd1a3..e461ab7 100644
> --- a/attrib/gatt.c
> +++ b/attrib/gatt.c
> @@ -871,6 +871,24 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
> return prepare_write(long_write);
> }
>
> +guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
> + const uint8_t *value, size_t vlen,
> + GAttribResultFunc func,
> + gpointer user_data)
> +{
> + uint8_t *buf;
> + guint16 plen;
> + size_t buflen;
> +
> + buf = g_attrib_get_buffer(attrib, &buflen);
> +
> + plen = enc_prep_write_req(handle, 0, value, vlen, buf, buflen);
> + if (!plen)
> + return 0;
> +
> + return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
> +}
> +
> guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
> gpointer user_data)
> {
> diff --git a/attrib/gatt.h b/attrib/gatt.h
> index c65bf6c..76820e0 100644
> --- a/attrib/gatt.h
> +++ b/attrib/gatt.h
> @@ -84,6 +84,12 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
> size_t vlen, GAttribResultFunc func,
> gpointer user_data);
>
> +guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
> + const uint8_t *value, size_t vlen,
> + GAttribResultFunc func,
> + gpointer user_data);
> +
> +

Just a minor: double empty line.

> guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
> GAttribResultFunc func, gpointer user_data);
>
>

--
Best regards,
Szymon Janc

2014-04-14 14:23:09

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 00/10] android/gatt: GATT Client write types support

Hi Łukasz,

On Sunday 13 of April 2014 00:00:21 Lukasz Rymanowski wrote:
> This patch set adds support for different write types.
> For this I had to expose some additional API from attrib.
>
> Only signed write left to implement.
>
> This patch set also do some code cleaning.
>
> Lukasz Rymanowski (10):
> attrib: Add API for reliable write
> attrib: Expose write execute
> android/gatt: Add helper to create descr_data
> android/gatt: Avoid double helper struct for read/write characteristic
> android/gatt: Add helper to create characteristic op data
> android/gatt: Fix error msg
> android/gatt: Daemon accepts only default write type
> android/gatt: Add support for reliable write
> android/gatt: Add support for write execute
> android/gatt: Add support for write without response
>
> android/gatt.c | 264 ++++++++++++++++++++++++++++++++++++++++++---------------
> attrib/gatt.c | 24 ++++++
> attrib/gatt.h | 8 ++
> 3 files changed, 226 insertions(+), 70 deletions(-)
>
>

Patches 3-7 are now pushed. Thanks.

I moved GATT write types definitions to HAL IPC.

--
Best regards,
Szymon Janc

2014-04-12 22:00:24

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 03/10] android/gatt: Add helper to create descr_data

---
android/gatt.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 243e02f..d04294c 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -2155,6 +2155,27 @@ static void read_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
free(cb_data);
}

+static struct desc_data *create_desc_data(int32_t conn_id,
+ const struct element_id *s_id,
+ const struct element_id *ch_id,
+ const struct element_id *d_id,
+ uint8_t primary)
+{
+ struct desc_data *d;
+
+ d = new0(struct desc_data, 1);
+ if (!d)
+ return NULL;
+
+ d->conn_id = conn_id;
+ d->srvc_id = s_id;
+ d->char_id = ch_id;
+ d->descr_id = d_id;
+ d->primary = primary;
+
+ return d;
+}
+
static void handle_client_read_descriptor(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_read_descriptor *cmd = buf;
@@ -2203,7 +2224,8 @@ static void handle_client_read_descriptor(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct desc_data, 1);
+ cb_data = create_desc_data(conn_id, &srvc->id, &ch->id, &descr->id,
+ primary);
if (!cb_data) {
error("gatt: Read descr. could not allocate callback data");

@@ -2211,12 +2233,6 @@ static void handle_client_read_descriptor(const void *buf, uint16_t len)
goto failed;
}

- cb_data->conn_id = conn_id;
- cb_data->srvc_id = &srvc->id;
- cb_data->char_id = &ch->id;
- cb_data->descr_id = &descr->id;
- cb_data->primary = primary;
-
if (!gatt_read_char(dev->attrib, descr->handle, read_desc_cb,
cb_data)) {
free(cb_data);
@@ -2330,7 +2346,8 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct desc_data, 1);
+ cb_data = create_desc_data(conn_id, &srvc->id, &ch->id, &descr->id,
+ primary);
if (!cb_data) {
error("gatt: Write descr. could not allocate callback data");

@@ -2338,12 +2355,6 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
goto failed;
}

- cb_data->conn_id = conn_id;
- cb_data->srvc_id = &srvc->id;
- cb_data->char_id = &ch->id;
- cb_data->descr_id = &descr->id;
- cb_data->primary = primary;
-
if (!gatt_write_char(dev->attrib, descr->handle, cmd->value, cmd->len,
write_descr_cb, cb_data)) {
free(cb_data);
--
1.8.4


2014-04-12 22:00:25

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 04/10] android/gatt: Avoid double helper struct for read/write characteristic

This patch combine two helper structs for operations on characteristics
to one.

Also use pointers inside this struct instread of raw data.
---
android/gatt.c | 51 ++++++++++++++++++++++-----------------------------
1 file changed, 22 insertions(+), 29 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index d04294c..adba29e 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1864,17 +1864,17 @@ failed:
HAL_OP_GATT_CLIENT_GET_DESCRIPTOR, status);
}

-struct read_char_data {
+struct char_op_data {
int32_t conn_id;
- struct element_id srvc_id;
- struct element_id char_id;
+ const struct element_id *srvc_id;
+ const struct element_id *char_id;
uint8_t primary;
};

static void send_client_read_char_notify(int32_t status, const uint8_t *pdu,
uint16_t len, int32_t conn_id,
- struct element_id *srvc_id,
- struct element_id *char_id,
+ const struct element_id *s_id,
+ const struct element_id *ch_id,
uint8_t primary)
{
uint8_t buf[IPC_MTU];
@@ -1886,8 +1886,8 @@ static void send_client_read_char_notify(int32_t status, const uint8_t *pdu,
ev->conn_id = conn_id;
ev->status = status;

- element_id_to_hal_srvc_id(srvc_id, primary, &ev->data.srvc_id);
- element_id_to_hal_gatt_id(char_id, &ev->data.char_id);
+ element_id_to_hal_srvc_id(s_id, primary, &ev->data.srvc_id);
+ element_id_to_hal_gatt_id(ch_id, &ev->data.char_id);

if (pdu) {
vlen = dec_read_resp(pdu, len, ev->data.value, sizeof(buf));
@@ -1907,10 +1907,10 @@ static void send_client_read_char_notify(int32_t status, const uint8_t *pdu,
static void read_char_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct read_char_data *data = user_data;
+ struct char_op_data *data = user_data;

send_client_read_char_notify(status, pdu, len, data->conn_id,
- &data->srvc_id, &data->char_id,
+ data->srvc_id, data->char_id,
data->primary);

free(data);
@@ -1919,7 +1919,7 @@ static void read_char_cb(guint8 status, const guint8 *pdu, guint16 len,
static void handle_client_read_characteristic(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_read_characteristic *cmd = buf;
- struct read_char_data *cb_data;
+ struct char_op_data *cb_data;
struct characteristic *ch;
struct gatt_device *dev;
struct service *srvc;
@@ -1948,7 +1948,7 @@ static void handle_client_read_characteristic(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct read_char_data, 1);
+ cb_data = new0(struct char_op_data, 1);
if (!cb_data) {
error("gatt: Cannot allocate cb data");
status = HAL_STATUS_NOMEM;
@@ -1957,8 +1957,8 @@ static void handle_client_read_characteristic(const void *buf, uint16_t len)

cb_data->conn_id = cmd->conn_id;
cb_data->primary = cmd->srvc_id.is_primary;
- cb_data->srvc_id = srvc_id;
- cb_data->char_id = char_id;
+ cb_data->srvc_id = &srvc->id;
+ cb_data->char_id = &ch->id;

if (!gatt_read_char(dev->attrib, ch->ch.value_handle,
read_char_cb, cb_data)) {
@@ -1984,16 +1984,9 @@ failed:
cmd->srvc_id.is_primary);
}

-struct write_char_data {
- int32_t conn_id;
- struct element_id srvc_id;
- struct element_id char_id;
- uint8_t primary;
-};
-
static void send_client_write_char_notify(int32_t status, int32_t conn_id,
- struct element_id *srvc_id,
- struct element_id *char_id,
+ const struct element_id *srvc_id,
+ const struct element_id *char_id,
uint8_t primary)
{
struct hal_ev_gatt_client_write_characteristic ev;
@@ -2014,10 +2007,10 @@ static void send_client_write_char_notify(int32_t status, int32_t conn_id,
static void write_char_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct write_char_data *data = user_data;
+ struct char_op_data *data = user_data;

- send_client_write_char_notify(status, data->conn_id, &data->srvc_id,
- &data->char_id, data->primary);
+ send_client_write_char_notify(status, data->conn_id, data->srvc_id,
+ data->char_id, data->primary);

free(data);
}
@@ -2025,7 +2018,7 @@ static void write_char_cb(guint8 status, const guint8 *pdu, guint16 len,
static void handle_client_write_characteristic(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_write_characteristic *cmd = buf;
- struct write_char_data *cb_data;
+ struct char_op_data *cb_data;
struct characteristic *ch;
struct gatt_device *dev;
struct service *srvc;
@@ -2058,7 +2051,7 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct write_char_data, 1);
+ cb_data = new0(struct char_op_data, 1);
if (!cb_data) {
error("gatt: Cannot allocate call data");
status = HAL_STATUS_NOMEM;
@@ -2067,8 +2060,8 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)

cb_data->conn_id = cmd->conn_id;
cb_data->primary = cmd->srvc_id.is_primary;
- cb_data->srvc_id = srvc_id;
- cb_data->char_id = char_id;
+ cb_data->srvc_id = &srvc->id;
+ cb_data->char_id = &ch->id;

if (!gatt_write_char(dev->attrib, ch->ch.value_handle, cmd->value,
cmd->len, write_char_cb, cb_data)) {
--
1.8.4


2014-04-12 22:00:26

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 05/10] android/gatt: Add helper to create characteristic op data

This patch adds helper to create data needed for read/write
characteristic
---
android/gatt.c | 35 +++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index adba29e..9d45968 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1871,6 +1871,25 @@ struct char_op_data {
uint8_t primary;
};

+static struct char_op_data *create_char_op_data(int32_t conn_id,
+ const struct element_id *s_id,
+ const struct element_id *ch_id,
+ bool primary)
+{
+ struct char_op_data *d;
+
+ d = new0(struct char_op_data, 1);
+ if (!d)
+ return NULL;
+
+ d->conn_id = conn_id;
+ d->srvc_id = s_id;
+ d->char_id = ch_id;
+ d->primary = primary;
+
+ return d;
+}
+
static void send_client_read_char_notify(int32_t status, const uint8_t *pdu,
uint16_t len, int32_t conn_id,
const struct element_id *s_id,
@@ -1948,18 +1967,14 @@ static void handle_client_read_characteristic(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct char_op_data, 1);
+ cb_data = create_char_op_data(cmd->conn_id, &srvc->id, &ch->id,
+ cmd->srvc_id.is_primary);
if (!cb_data) {
error("gatt: Cannot allocate cb data");
status = HAL_STATUS_NOMEM;
goto failed;
}

- cb_data->conn_id = cmd->conn_id;
- cb_data->primary = cmd->srvc_id.is_primary;
- cb_data->srvc_id = &srvc->id;
- cb_data->char_id = &ch->id;
-
if (!gatt_read_char(dev->attrib, ch->ch.value_handle,
read_char_cb, cb_data)) {
error("gatt: Cannot read characteristic with inst_id: %d",
@@ -2051,18 +2066,14 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)
goto failed;
}

- cb_data = new0(struct char_op_data, 1);
+ cb_data = create_char_op_data(cmd->conn_id, &srvc->id, &ch->id,
+ cmd->srvc_id.is_primary);
if (!cb_data) {
error("gatt: Cannot allocate call data");
status = HAL_STATUS_NOMEM;
goto failed;
}

- cb_data->conn_id = cmd->conn_id;
- cb_data->primary = cmd->srvc_id.is_primary;
- cb_data->srvc_id = &srvc->id;
- cb_data->char_id = &ch->id;
-
if (!gatt_write_char(dev->attrib, ch->ch.value_handle, cmd->value,
cmd->len, write_char_cb, cb_data)) {
error("gatt: Cannot read characteristic with inst_id: %d",
--
1.8.4


2014-04-12 22:00:28

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 07/10] android/gatt: Daemon accepts only default write type

With this patch daemon accepts only default write type. For other types
it correctly replies with HAL_STATUS_UNSUPPORTED
---
android/gatt.c | 50 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 523a141..c98a4f1 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -54,6 +54,8 @@
#define GATT_SUCCESS 0x00000000
#define GATT_FAILURE 0x00000101

+#define GATT_WRITE_DEFAULT 0x02
+
struct gatt_client {
int32_t id;
uint8_t uuid[16];
@@ -2033,13 +2035,14 @@ static void write_char_cb(guint8 status, const guint8 *pdu, guint16 len,
static void handle_client_write_characteristic(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_write_characteristic *cmd = buf;
- struct char_op_data *cb_data;
+ struct char_op_data *cb_data = NULL;
struct characteristic *ch;
struct gatt_device *dev;
struct service *srvc;
struct element_id srvc_id;
struct element_id char_id;
uint8_t status;
+ guint res;

DBG("");

@@ -2074,28 +2077,41 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)
goto failed;
}

- if (!gatt_write_char(dev->attrib, ch->ch.value_handle, cmd->value,
- cmd->len, write_char_cb, cb_data)) {
- error("gatt: Cannot write characteristic with inst_id: %d",
+ switch (cmd->write_type) {
+ case GATT_WRITE_DEFAULT:
+ res = gatt_write_char(dev->attrib, ch->ch.value_handle,
+ cmd->value, cmd->len,
+ write_char_cb, cb_data);
+ break;
+ default:
+ error("gatt: Write type %d unsupported", cmd->write_type);
+ status = HAL_STATUS_UNSUPPORTED;
+ goto failed;
+ }
+
+ if (!res) {
+ error("gatt: Cannot write char. with inst_id: %d",
cmd->gatt_id.inst_id);
status = HAL_STATUS_FAILED;
- free(cb_data);
goto failed;
}

status = HAL_STATUS_SUCCESS;

failed:
+
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_WRITE_CHARACTERISTIC, status);

/* We should send notification with service, characteristic id in case
* of errors.
*/
- if (status != HAL_STATUS_SUCCESS)
+ if (status != HAL_STATUS_SUCCESS) {
send_client_write_char_notify(GATT_FAILURE, cmd->conn_id,
&srvc_id, &char_id,
cmd->srvc_id.is_primary);
+ free(cb_data);
+ }
}

static void send_client_descr_read_notify(int32_t status, const uint8_t *pdu,
@@ -2298,7 +2314,7 @@ static void write_descr_cb(guint8 status, const guint8 *pdu, guint16 len,
static void handle_client_write_descriptor(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_write_descriptor *cmd = buf;
- struct desc_data *cb_data;
+ struct desc_data *cb_data = NULL;
struct characteristic *ch;
struct descriptor *descr;
struct service *srvc;
@@ -2309,6 +2325,7 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
int32_t conn_id;
uint8_t primary;
uint8_t status;
+ guint res;

DBG("");

@@ -2359,10 +2376,19 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
goto failed;
}

- if (!gatt_write_char(dev->attrib, descr->handle, cmd->value, cmd->len,
- write_descr_cb, cb_data)) {
- free(cb_data);
+ switch (cmd->write_type) {
+ case GATT_WRITE_DEFAULT:
+ res = gatt_write_char(dev->attrib, descr->handle, cmd->value,
+ cmd->len, write_descr_cb, cb_data);
+ break;
+ default:
+ error("gatt: Write type %d unsupported", cmd->write_type);
+ status = HAL_STATUS_UNSUPPORTED;
+ goto failed;
+ }

+ if (!res) {
+ error("gatt: Write desc, could not write desc");
status = HAL_STATUS_FAILED;
goto failed;
}
@@ -2370,9 +2396,11 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;

failed:
- if (status != HAL_STATUS_SUCCESS)
+ if (status != HAL_STATUS_SUCCESS) {
send_client_descr_write_notify(GATT_FAILURE, conn_id, &srvc_id,
&char_id, &descr_id, primary);
+ free(cb_data);
+ }

ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_WRITE_DESCRIPTOR, status);
--
1.8.4


2014-04-12 22:00:29

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 08/10] android/gatt: Add support for reliable write

This patch add support for reliable write
---
android/gatt.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/android/gatt.c b/android/gatt.c
index c98a4f1..e5da1b2 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -55,6 +55,7 @@
#define GATT_FAILURE 0x00000101

#define GATT_WRITE_DEFAULT 0x02
+#define GATT_WRITE_RELIABLE 0x03

struct gatt_client {
int32_t id;
@@ -2078,6 +2079,11 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)
}

switch (cmd->write_type) {
+ case GATT_WRITE_RELIABLE:
+ res = gatt_reliable_write_char(dev->attrib, ch->ch.value_handle,
+ cmd->value, cmd->len,
+ write_char_cb, cb_data);
+ break;
case GATT_WRITE_DEFAULT:
res = gatt_write_char(dev->attrib, ch->ch.value_handle,
cmd->value, cmd->len,
@@ -2377,6 +2383,12 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
}

switch (cmd->write_type) {
+ case GATT_WRITE_RELIABLE:
+ res = gatt_reliable_write_char(dev->attrib, descr->handle,
+ cmd->value, cmd->len,
+ write_descr_cb,
+ cb_data);
+ break;
case GATT_WRITE_DEFAULT:
res = gatt_write_char(dev->attrib, descr->handle, cmd->value,
cmd->len, write_descr_cb, cb_data);
--
1.8.4


2014-04-12 22:00:31

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 10/10] android/gatt: Add support for write without response

---
android/gatt.c | 55 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 6fcc977..ce7c0d3 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -54,6 +54,7 @@
#define GATT_SUCCESS 0x00000000
#define GATT_FAILURE 0x00000101

+#define GATT_WRITE_NO_RESPONSE 0x01
#define GATT_WRITE_DEFAULT 0x02
#define GATT_WRITE_RELIABLE 0x03

@@ -2070,15 +2071,22 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)
goto failed;
}

- cb_data = create_char_op_data(cmd->conn_id, &srvc->id, &ch->id,
+ if (cmd->write_type != GATT_WRITE_NO_RESPONSE) {
+ cb_data = create_char_op_data(cmd->conn_id, &srvc->id, &ch->id,
cmd->srvc_id.is_primary);
- if (!cb_data) {
- error("gatt: Cannot allocate call data");
- status = HAL_STATUS_NOMEM;
- goto failed;
+ if (!cb_data) {
+ error("gatt: Cannot allocate call data");
+ status = HAL_STATUS_NOMEM;
+ goto failed;
+ }
}

switch (cmd->write_type) {
+ case GATT_WRITE_NO_RESPONSE:
+ res = gatt_write_cmd(dev->attrib, ch->ch.value_handle,
+ cmd->value, cmd->len,
+ NULL, NULL);
+ break;
case GATT_WRITE_RELIABLE:
res = gatt_reliable_write_char(dev->attrib, ch->ch.value_handle,
cmd->value, cmd->len,
@@ -2110,10 +2118,14 @@ failed:
HAL_OP_GATT_CLIENT_WRITE_CHARACTERISTIC, status);

/* We should send notification with service, characteristic id in case
- * of errors.
+ * of error and write with no response
*/
- if (status != HAL_STATUS_SUCCESS) {
- send_client_write_char_notify(GATT_FAILURE, cmd->conn_id,
+ if (status != HAL_STATUS_SUCCESS ||
+ cmd->write_type == GATT_WRITE_NO_RESPONSE) {
+ int32_t gatt_status = (status == HAL_STATUS_SUCCESS) ?
+ GATT_SUCCESS : GATT_FAILURE;
+
+ send_client_write_char_notify(gatt_status, cmd->conn_id,
&srvc_id, &char_id,
cmd->srvc_id.is_primary);
free(cb_data);
@@ -2373,21 +2385,28 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
goto failed;
}

- cb_data = create_desc_data(conn_id, &srvc->id, &ch->id, &descr->id,
- primary);
- if (!cb_data) {
- error("gatt: Write descr. could not allocate callback data");
+ if (cmd->write_type != GATT_WRITE_NO_RESPONSE) {
+ cb_data = create_desc_data(conn_id, &srvc->id, &ch->id,
+ &descr->id, primary);
+ if (!cb_data) {
+ error("gatt: Write descr. could not allocate cb_data");

- status = HAL_STATUS_NOMEM;
- goto failed;
+ status = HAL_STATUS_NOMEM;
+ goto failed;
+ }
}

switch (cmd->write_type) {
+ case GATT_WRITE_NO_RESPONSE:
+ res = gatt_write_cmd(dev->attrib, descr->handle, cmd->value,
+ cmd->len, NULL , NULL);
+ break;
case GATT_WRITE_RELIABLE:
res = gatt_reliable_write_char(dev->attrib, descr->handle,
cmd->value, cmd->len,
write_descr_cb,
cb_data);
+
break;
case GATT_WRITE_DEFAULT:
res = gatt_write_char(dev->attrib, descr->handle, cmd->value,
@@ -2408,8 +2427,12 @@ static void handle_client_write_descriptor(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;

failed:
- if (status != HAL_STATUS_SUCCESS) {
- send_client_descr_write_notify(GATT_FAILURE, conn_id, &srvc_id,
+ if (status != HAL_STATUS_SUCCESS ||
+ cmd->write_type == GATT_WRITE_NO_RESPONSE) {
+ int32_t gatt_status = (status == HAL_STATUS_SUCCESS) ?
+ GATT_SUCCESS : GATT_FAILURE;
+
+ send_client_descr_write_notify(gatt_status, conn_id, &srvc_id,
&char_id, &descr_id, primary);
free(cb_data);
}
--
1.8.4


2014-04-12 22:00:30

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 09/10] android/gatt: Add support for write execute

This patch add support for write execute. There is possible to write or
cancel all prepared data
---
android/gatt.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/android/gatt.c b/android/gatt.c
index e5da1b2..6fcc977 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -2418,12 +2418,58 @@ failed:
HAL_OP_GATT_CLIENT_WRITE_DESCRIPTOR, status);
}

+static void send_client_write_execute_notify(int32_t id, int32_t status)
+{
+ struct hal_ev_gatt_client_exec_write ev;
+
+ ev.conn_id = id;
+ ev.status = status;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+ HAL_EV_GATT_CLIENT_EXEC_WRITE,
+ sizeof(ev), &ev);
+}
+
+static void write_execute_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ send_client_write_execute_notify(PTR_TO_INT(user_data), status);
+}
+
static void handle_client_execute_write(const void *buf, uint16_t len)
{
+ const struct hal_cmd_gatt_client_execute_write *cmd = buf;
+ struct gatt_device *dev;
+ uint8_t status;
+ uint8_t flags;
+
DBG("");

+ dev = queue_find(conn_list, match_dev_by_conn_id,
+ INT_TO_PTR(cmd->conn_id));
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto reply;
+ }
+
+ flags = cmd->execute ? ATT_WRITE_ALL_PREP_WRITES :
+ ATT_CANCEL_ALL_PREP_WRITES;
+
+ if (!gatt_execute_write(dev->attrib, flags, write_execute_cb,
+ INT_TO_PTR(cmd->conn_id))) {
+ error("gatt: Could not send execute write");
+ status = HAL_STATUS_FAILED;
+ goto reply;
+ }
+
+ status = HAL_STATUS_SUCCESS;
+reply:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
- HAL_OP_GATT_CLIENT_EXECUTE_WRITE, HAL_STATUS_FAILED);
+ HAL_OP_GATT_CLIENT_EXECUTE_WRITE, status);
+
+ /* In case of early error send also notification.*/
+ if (status != HAL_STATUS_SUCCESS)
+ send_client_write_execute_notify(cmd->conn_id, GATT_FAILURE);
}

static void handle_notification(const uint8_t *pdu, uint16_t len,
--
1.8.4


2014-04-12 22:00:27

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 06/10] android/gatt: Fix error msg

---
android/gatt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/gatt.c b/android/gatt.c
index 9d45968..523a141 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -2076,7 +2076,7 @@ static void handle_client_write_characteristic(const void *buf, uint16_t len)

if (!gatt_write_char(dev->attrib, ch->ch.value_handle, cmd->value,
cmd->len, write_char_cb, cb_data)) {
- error("gatt: Cannot read characteristic with inst_id: %d",
+ error("gatt: Cannot write characteristic with inst_id: %d",
cmd->gatt_id.inst_id);
status = HAL_STATUS_FAILED;
free(cb_data);
--
1.8.4


2014-04-12 22:00:23

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 02/10] attrib: Expose write execute

This is needed to cover Android API
---
attrib/gatt.c | 6 ++++++
attrib/gatt.h | 2 ++
2 files changed, 8 insertions(+)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index e461ab7..f5917db 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -871,6 +871,12 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
return prepare_write(long_write);
}

+guint gatt_execute_write(GAttrib *attrib, uint8_t flags,
+ GAttribResultFunc func, gpointer user_data)
+{
+ return execute_write(attrib, flags, func, user_data);
+}
+
guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
const uint8_t *value, size_t vlen,
GAttribResultFunc func,
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 76820e0..3fe6041 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -89,6 +89,8 @@ guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
GAttribResultFunc func,
gpointer user_data);

+guint gatt_execute_write(GAttrib *attrib, uint8_t flags,
+ GAttribResultFunc func, gpointer user_data);

guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
GAttribResultFunc func, gpointer user_data);
--
1.8.4


2014-04-12 22:00:22

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 01/10] attrib: Add API for reliable write

Android expose to application api for reliable write. Therefore we need
to add this support to gattrib
---
attrib/gatt.c | 18 ++++++++++++++++++
attrib/gatt.h | 6 ++++++
2 files changed, 24 insertions(+)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index 49cd1a3..e461ab7 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -871,6 +871,24 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
return prepare_write(long_write);
}

+guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
+ const uint8_t *value, size_t vlen,
+ GAttribResultFunc func,
+ gpointer user_data)
+{
+ uint8_t *buf;
+ guint16 plen;
+ size_t buflen;
+
+ buf = g_attrib_get_buffer(attrib, &buflen);
+
+ plen = enc_prep_write_req(handle, 0, value, vlen, buf, buflen);
+ if (!plen)
+ return 0;
+
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
+}
+
guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index c65bf6c..76820e0 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -84,6 +84,12 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, const uint8_t *value,
size_t vlen, GAttribResultFunc func,
gpointer user_data);

+guint gatt_reliable_write_char(GAttrib *attrib, uint16_t handle,
+ const uint8_t *value, size_t vlen,
+ GAttribResultFunc func,
+ gpointer user_data);
+
+
guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
GAttribResultFunc func, gpointer user_data);

--
1.8.4