2014-06-27 15:16:02

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 01/10] android/health: Add error check when creating app

From: Andrei Emeltchenko <[email protected]>

---
android/health.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/android/health.c b/android/health.c
index 7d64a63..0eeb0bd 100644
--- a/android/health.c
+++ b/android/health.c
@@ -820,6 +820,8 @@ static void bt_health_register_app(const void *buf, uint16_t len)

app = create_health_app(app_name, provider, srv_name, srv_descr,
cmd->num_of_mdep);
+ if (!app)
+ goto fail;

if (!queue_push_tail(apps, app))
goto fail;
--
1.8.3.2



2014-06-29 12:18:27

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCHv4 01/10] android/health: Add error check when creating app

Hi Andrei,

On Friday 27 of June 2014 18:16:02 Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <[email protected]>
>
> ---
> android/health.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/android/health.c b/android/health.c
> index 7d64a63..0eeb0bd 100644
> --- a/android/health.c
> +++ b/android/health.c
> @@ -820,6 +820,8 @@ static void bt_health_register_app(const void *buf,
> uint16_t len)
>
> app = create_health_app(app_name, provider, srv_name, srv_descr,
> cmd->num_of_mdep);
> + if (!app)
> + goto fail;
>
> if (!queue_push_tail(apps, app))
> goto fail;

All patches applied, thanks.

--
BR
Szymon Janc

2014-06-27 15:16:11

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 10/10] android/pts: Update HDP test results

From: Andrei Emeltchenko <[email protected]>

Mark ECHO server tests passed.
---
android/pts-hdp.txt | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/android/pts-hdp.txt b/android/pts-hdp.txt
index 99aa2d6..f2b1528 100644
--- a/android/pts-hdp.txt
+++ b/android/pts-hdp.txt
@@ -1,7 +1,7 @@
PTS test results for HDP

PTS version: 5.1
-Tested: 17-June-2014
+Tested: 27-June-2014
Android version: 4.4.2

Results:
@@ -105,7 +105,11 @@ TC_SRC_HCT_BV_05_C N/A
TC_SRC_HCT_BV_06_C INC
TC_SRC_HCT_BV_07_C INC
TC_SRC_DE_BV_01_I INC
-TC_SRC_DE_BV_02_I INC
+TC_SRC_DE_BV_02_I PASS haltest:
+ hl register_application bluez-android Bluez
+ bluez-hdp health-device-profile 1
+ BTHL_MDEP_ROLE_SOURCE 4100
+ BTHL_CHANNEL_TYPE_RELIABLE pulse-oximeter
TC_SRC_DEP_BV_01_I INC
TC_SRC_DEP_BV_02_I N/A
TC_SNK_CON_BV_01_I PASS haltest:
@@ -195,7 +199,11 @@ TC_SNK_HCT_BV_05_C N/A
TC_SNK_HCT_BV_06_C INC
TC_SNK_HCT_BV_07_C INC
TC_SNK_DE_BV_01_I N/A
-TC_SNK_DE_BV_02_I INC
+TC_SNK_DE_BV_02_I PASS haltest:
+ hl register_application bluez-android Bluez
+ bluez-hdp health-device-profile 1
+ BTHL_MDEP_ROLE_SINK 4100
+ BTHL_CHANNEL_TYPE_RELIABLE pulse-oximeter
TC_SNK_DEP_BV_03_I INC
TC_SNK_DEP_BV_04_I INC
-------------------------------------------------------------------------------
--
1.8.3.2


2014-06-27 15:16:09

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 08/10] android/health: Add handling for ECHO service

From: Andrei Emeltchenko <[email protected]>

Reply received buffer back for ECHO service.
---
android/health.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/android/health.c b/android/health.c
index 8bd857d..1796d7c 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1056,9 +1056,71 @@ static int get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm)
return -1;
}

+static int send_echo_data(int sock, const void *buf, uint32_t size)
+{
+ const uint8_t *buf_b = buf;
+ uint32_t sent = 0;
+
+ while (sent < size) {
+ int n = write(sock, buf_b + sent, size - sent);
+ if (n < 0)
+ return -1;
+ sent += n;
+ }
+
+ return 0;
+}
+
+static gboolean serve_echo(GIOChannel *io, GIOCondition cond, gpointer data)
+{
+ struct health_channel *channel = data;
+ uint8_t buf[MCAP_DC_MTU];
+ int fd, len, ret;
+
+ DBG("channel %p", channel);
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ DBG("Error condition on channel");
+ return FALSE;
+ }
+
+ fd = g_io_channel_unix_get_fd(io);
+
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0) {
+ DBG("Error reading ECHO");
+ return FALSE;
+ }
+
+ ret = send_echo_data(fd, buf, len);
+ if (ret != len)
+ DBG("Error sending ECHO back");
+
+ return FALSE;
+}
+
static void mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data)
{
- DBG("Not Implemeneted");
+ struct health_channel *channel = data;
+
+ if (!channel->mdl)
+ channel->mdl = mcap_mdl_ref(mdl);
+
+ DBG("Data channel connected: mdl %p channel %p", mdl, channel);
+
+ if (channel->mdep_id == MDEP_ECHO) {
+ GIOChannel *io;
+ int fd;
+
+ fd = mcap_mdl_get_fd(channel->mdl);
+ if (fd < 0)
+ return;
+
+ io = g_io_channel_unix_new(fd);
+ g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN,
+ serve_echo, channel);
+ g_io_channel_unref(io);
+ }
}

static void mcap_mdl_closed_cb(struct mcap_mdl *mdl, void *data)
--
1.8.3.2


2014-06-27 15:16:06

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 05/10] android/health: Add channel connect

From: Andrei Emeltchenko <[email protected]>

Connect channel on incoming connection callback
---
android/health.c | 194 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 113 insertions(+), 81 deletions(-)

diff --git a/android/health.c b/android/health.c
index d7534ab..b7c24fd 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1107,14 +1107,127 @@ static void mcap_mdl_aborted_cb(struct mcap_mdl *mdl, void *data)
DBG("Not Implemeneted");
}

+static struct health_device *create_device(struct health_app *app,
+ const uint8_t *addr)
+{
+ struct health_device *dev;
+
+ if (!app)
+ return NULL;
+
+ /* create device and push it to devices queue */
+ dev = new0(struct health_device, 1);
+ if (!dev)
+ return NULL;
+
+ android2bdaddr(addr, &dev->dst);
+ dev->channels = queue_new();
+ if (!dev->channels) {
+ free_health_device(dev);
+ return NULL;
+ }
+
+ if (!queue_push_tail(app->devices, dev)) {
+ free_health_device(dev);
+ return NULL;
+ }
+
+ dev->app_id = app->id;
+
+ return dev;
+}
+
+static struct health_device *get_device(struct health_app *app,
+ const uint8_t *addr)
+{
+ struct health_device *dev;
+ bdaddr_t bdaddr;
+
+ android2bdaddr(addr, &bdaddr);
+ dev = queue_find(app->devices, match_dev_by_addr, &bdaddr);
+ if (dev)
+ return dev;
+
+ return create_device(app, addr);
+}
+
+static struct health_channel *create_channel(struct health_app *app,
+ uint8_t mdep_index,
+ struct health_device *dev)
+{
+ struct mdep_cfg *mdep;
+ struct health_channel *channel;
+ uint8_t index;
+ static unsigned int channel_id = 1;
+
+ DBG("mdep %u", mdep_index);
+
+ if (!dev || !app)
+ return NULL;
+
+ index = mdep_index + 1;
+ mdep = queue_find(app->mdeps, match_mdep_by_id, INT_TO_PTR(index));
+ if (!mdep)
+ return NULL;
+
+ /* create channel and push it to device */
+ channel = new0(struct health_channel, 1);
+ if (!channel)
+ return NULL;
+
+ channel->mdep_id = mdep->id;
+ channel->type = mdep->channel_type;
+ channel->id = channel_id++;
+ channel->dev = dev;
+
+ if (!queue_push_tail(dev->channels, channel)) {
+ free_health_channel(channel);
+ return NULL;
+ }
+
+ return channel;
+}
+
+static struct health_channel *connect_channel(struct mcap_mcl *mcl,
+ uint8_t mdepid)
+{
+ struct health_app *app;
+ struct health_device *device;
+ struct health_channel *channel = NULL;
+ bdaddr_t addr;
+
+ mcap_mcl_get_addr(mcl, &addr);
+
+ /* TODO: Search app for mdepid */
+
+ if (mdepid == MDEP_ECHO) {
+ /* For echo service take last app */
+ app = queue_peek_tail(apps);
+ if (!app)
+ return NULL;
+
+ device = get_device(app, (uint8_t *) &addr);
+ if (!device)
+ return NULL;
+
+ channel = create_channel(app, mdepid, device);
+ }
+
+ return channel;
+}
+
static uint8_t mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
uint16_t mdlid, uint8_t *conf, void *data)
{
GError *gerr = NULL;
+ struct health_channel *channel;

DBG("Data channel request: mdepid %u mdlid %u", mdepid, mdlid);

/* TODO: find / create device */
+ channel = connect_channel(mcl, mdepid);
+ if (!channel)
+ return MCAP_MDL_BUSY;

if (mdepid == MDEP_ECHO) {
switch (*conf) {
@@ -1511,92 +1624,11 @@ static int connect_mcl(struct health_channel *channel)
search_cb, channel, NULL, 0);
}

-static struct health_device *create_device(struct health_app *app,
- const uint8_t *addr)
-{
- struct health_device *dev;
-
- if (!app)
- return NULL;
-
- /* create device and push it to devices queue */
- dev = new0(struct health_device, 1);
- if (!dev)
- return NULL;
-
- android2bdaddr(addr, &dev->dst);
- dev->channels = queue_new();
- if (!dev->channels) {
- free_health_device(dev);
- return NULL;
- }
-
- if (!queue_push_tail(app->devices, dev)) {
- free_health_device(dev);
- return NULL;
- }
-
- dev->app_id = app->id;
-
- return dev;
-}
-
static struct health_app *get_app(uint16_t app_id)
{
return queue_find(apps, match_app_by_id, INT_TO_PTR(app_id));
}

-static struct health_device *get_device(struct health_app *app,
- const uint8_t *addr)
-{
- struct health_device *dev;
- bdaddr_t bdaddr;
-
- android2bdaddr(addr, &bdaddr);
- dev = queue_find(app->devices, match_dev_by_addr, &bdaddr);
- if (dev)
- return dev;
-
- return create_device(app, addr);
-}
-
-static struct health_channel *create_channel(struct health_app *app,
- uint8_t mdep_index,
- struct health_device *dev)
-{
- struct mdep_cfg *mdep;
- struct health_channel *channel;
- uint8_t index;
- static unsigned int channel_id = 1;
-
- DBG("mdep %u", mdep_index);
-
- if (!dev || !app)
- return NULL;
-
- index = mdep_index + 1;
- mdep = queue_find(app->mdeps, match_mdep_by_id, INT_TO_PTR(index));
- if (!mdep)
- return NULL;
-
- /* create channel and push it to device */
- channel = new0(struct health_channel, 1);
- if (!channel)
- return NULL;
-
- channel->mdep_id = mdep->id;
- channel->type = mdep->channel_type;
- channel->id = channel_id++;
- channel->dev = dev;
-
- if (!queue_push_tail(dev->channels, channel)) {
- free_health_channel(channel);
- return NULL;
- }
-
- return channel;
-}
-
static struct health_channel *get_channel(struct health_app *app,
uint8_t mdep_index,
struct health_device *dev)
--
1.8.3.2


2014-06-27 15:16:07

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 06/10] android/health: Assign channel to user_data

From: Andrei Emeltchenko <[email protected]>

Assign channel for incoming connections when it is created.
---
android/health.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/android/health.c b/android/health.c
index b7c24fd..9551408 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1213,6 +1213,9 @@ static struct health_channel *connect_channel(struct mcap_mcl *mcl,
channel = create_channel(app, mdepid, device);
}

+ /* Device is created here */
+ mcl->cb->user_data = channel;
+
return channel;
}

--
1.8.3.2


2014-06-27 15:16:04

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 03/10] android/health: Add handling MDL connection request

From: Andrei Emeltchenko <[email protected]>

Handles MDL connection request for ECHO service
---
android/health.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/android/health.c b/android/health.c
index 9857240..fd79ce7 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1110,7 +1110,38 @@ static void mcap_mdl_aborted_cb(struct mcap_mdl *mdl, void *data)
static uint8_t mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
uint16_t mdlid, uint8_t *conf, void *data)
{
- DBG("Not Implemeneted");
+ GError *gerr = NULL;
+
+ DBG("Data channel request: mdepid %u mdlid %u", mdepid, mdlid);
+
+ /* TODO: find / create device */
+
+ if (mdepid == MDEP_ECHO) {
+ switch (*conf) {
+ case CHANNEL_TYPE_ANY:
+ *conf = CHANNEL_TYPE_RELIABLE;
+ case CHANNEL_TYPE_RELIABLE:
+ break;
+ case CHANNEL_TYPE_STREAM:
+ return MCAP_CONFIGURATION_REJECTED;
+ default:
+ /* Special case defined in HDP spec 3.4. When an invalid
+ * configuration is received we shall close the MCL when
+ * we are still processing the callback. */
+ /* TODO close device */
+ return MCAP_CONFIGURATION_REJECTED; /* not processed */
+ }
+
+ if (!mcap_set_data_chan_mode(mcap, L2CAP_MODE_ERTM, &gerr)) {
+ error("Error: %s", gerr->message);
+ g_error_free(gerr);
+ return MCAP_MDL_BUSY;
+ }
+
+ /* TODO: Create channel */
+
+ return MCAP_SUCCESS;
+ }

return MCAP_SUCCESS;
}
--
1.8.3.2


2014-06-27 15:16:10

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 09/10] android/health: Improve debug

From: Andrei Emeltchenko <[email protected]>

---
android/health.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/android/health.c b/android/health.c
index 1796d7c..43e5967 100644
--- a/android/health.c
+++ b/android/health.c
@@ -164,6 +164,8 @@ static void free_health_channel(void *data)
{
struct health_channel *channel = data;

+ DBG("channel %p", channel);
+
if (!channel)
return;

@@ -1147,12 +1149,13 @@ static void mcap_mdl_deleted_cb(struct mcap_mdl *mdl, void *data)
struct health_channel *channel = data;
struct health_device *dev;

- DBG("");
-
if (!channel)
return;

dev = channel->dev;
+
+ DBG("device %p channel %p mdl %p", dev, channel, mdl);
+
/* mdl == NULL means, delete all mdls */
if (!mdl) {
queue_foreach(dev->channels, notify_channel, NULL);
@@ -1270,6 +1273,8 @@ static struct health_channel *connect_channel(struct mcap_mcl *mcl,
struct health_channel *channel = NULL;
bdaddr_t addr;

+ DBG("mcl %p mdepid %u", mcl, mdepid);
+
mcap_mcl_get_addr(mcl, &addr);

/* TODO: Search app for mdepid */
@@ -1565,7 +1570,7 @@ static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)

if (!get_mdep_from_rec(recs->data, mdep->role, mdep->data_type,
&mdep_id)) {
- error("health: no matching MDEP found");
+ error("health: no matching MDEP: %u", channel->mdep_id);
goto fail;
}

--
1.8.3.2


2014-06-27 15:16:08

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 07/10] android/health: Create mdep for ECHO channel

From: Andrei Emeltchenko <[email protected]>

---
android/health.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/android/health.c b/android/health.c
index 9551408..8bd857d 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1157,7 +1157,6 @@ static struct health_channel *create_channel(struct health_app *app,
{
struct mdep_cfg *mdep;
struct health_channel *channel;
- uint8_t index;
static unsigned int channel_id = 1;

DBG("mdep %u", mdep_index);
@@ -1165,10 +1164,23 @@ static struct health_channel *create_channel(struct health_app *app,
if (!dev || !app)
return NULL;

- index = mdep_index + 1;
- mdep = queue_find(app->mdeps, match_mdep_by_id, INT_TO_PTR(index));
- if (!mdep)
- return NULL;
+ mdep = queue_find(app->mdeps, match_mdep_by_id, INT_TO_PTR(mdep_index));
+ if (!mdep) {
+ if (mdep_index == MDEP_ECHO) {
+ mdep = new0(struct mdep_cfg, 1);
+ if (!mdep)
+ return NULL;
+
+ /* Leave other configuration zeroes */
+ mdep->id = MDEP_ECHO;
+
+ if (!queue_push_tail(app->mdeps, mdep)) {
+ free_mdep_cfg(mdep);
+ return NULL;
+ }
+ } else
+ return NULL;
+ }

/* create channel and push it to device */
channel = new0(struct health_channel, 1);
--
1.8.3.2


2014-06-27 15:16:03

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 02/10] android/health: Add HDP definitions

From: Andrei Emeltchenko <[email protected]>

---
android/health.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/android/health.c b/android/health.c
index 0eeb0bd..9857240 100644
--- a/android/health.c
+++ b/android/health.c
@@ -60,6 +60,10 @@
#define CHANNEL_TYPE_RELIABLE 0x01
#define CHANNEL_TYPE_STREAM 0x02

+#define MDEP_ECHO 0x00
+#define MDEP_INITIAL 0x01
+#define MDEP_FINAL 0x7F
+
static bdaddr_t adapter_addr;
static struct ipc *hal_ipc = NULL;
static struct queue *apps = NULL;
--
1.8.3.2


2014-06-27 15:16:05

by Andrei Emeltchenko

[permalink] [raw]
Subject: [PATCHv4 04/10] android/health: Refactor channel creation

From: Andrei Emeltchenko <[email protected]>

Avoid using app_id when we shall use app structure itself. Otherwise we
end up with unnecessary searches for app and problems for incoming
connections.
---
android/health.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/android/health.c b/android/health.c
index fd79ce7..d7534ab 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1536,46 +1536,42 @@ static struct health_device *create_device(struct health_app *app,
return NULL;
}

+ dev->app_id = app->id;
+
return dev;
}

-static struct health_device *get_device(uint16_t app_id, const uint8_t *addr)
+static struct health_app *get_app(uint16_t app_id)
+{
+ return queue_find(apps, match_app_by_id, INT_TO_PTR(app_id));
+}
+
+static struct health_device *get_device(struct health_app *app,
+ const uint8_t *addr)
{
- struct health_app *app;
struct health_device *dev;
bdaddr_t bdaddr;

- app = queue_find(apps, match_app_by_id, INT_TO_PTR(app_id));
- if (!app)
- return NULL;
-
android2bdaddr(addr, &bdaddr);
dev = queue_find(app->devices, match_dev_by_addr, &bdaddr);
if (dev)
return dev;

- dev = create_device(app, addr);
- if (dev)
- dev->app_id = app_id;
-
- return dev;
+ return create_device(app, addr);
}

-static struct health_channel *create_channel(uint16_t app_id,
+static struct health_channel *create_channel(struct health_app *app,
uint8_t mdep_index,
struct health_device *dev)
{
- struct health_app *app;
struct mdep_cfg *mdep;
struct health_channel *channel;
uint8_t index;
static unsigned int channel_id = 1;

- if (!dev)
- return NULL;
+ DBG("mdep %u", mdep_index);

- app = queue_find(apps, match_app_by_id, INT_TO_PTR(app_id));
- if (!app)
+ if (!dev || !app)
return NULL;

index = mdep_index + 1;
@@ -1601,7 +1597,7 @@ static struct health_channel *create_channel(uint16_t app_id,
return channel;
}

-static struct health_channel *get_channel(uint16_t app_id,
+static struct health_channel *get_channel(struct health_app *app,
uint8_t mdep_index,
struct health_device *dev)
{
@@ -1617,7 +1613,7 @@ static struct health_channel *get_channel(uint16_t app_id,
if (channel)
return channel;

- return create_channel(app_id, mdep_index, dev);
+ return create_channel(app, index, dev);
}

static void bt_health_connect_channel(const void *buf, uint16_t len)
@@ -1626,14 +1622,19 @@ static void bt_health_connect_channel(const void *buf, uint16_t len)
struct hal_rsp_health_connect_channel rsp;
struct health_device *dev = NULL;
struct health_channel *channel = NULL;
+ struct health_app *app;

DBG("");

- dev = get_device(cmd->app_id, cmd->bdaddr);
+ app = get_app(cmd->app_id);
+ if (!app)
+ goto fail;
+
+ dev = get_device(app, cmd->bdaddr);
if (!dev)
goto fail;

- channel = get_channel(cmd->app_id, cmd->mdep_index, dev);
+ channel = get_channel(app, cmd->mdep_index, dev);
if (!channel)
goto fail;

--
1.8.3.2