Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH_v2 0/6] HDP initial implementaion
@ 2014-06-16 15:01 Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 1/6] android/health: Cache health application data on app register call Ravi kumar Veeramally
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

v2: Fixed comments from Szymon (optimized cache patch,
    split notify patch, other issues).
v1: Fixed comments from szymon.

RFC_v2: Fixed comments by szymon and fixed issues while sebastian
testing with PTS.

RFC_v1: patchset is initial implementaion for HDP at daemon side.
Cacheing application data and prepare SDP record based on MDEPs
configuration and notify app state.

Ravi kumar Veeramally (6):
  android/health: Cache health application data on app register call
  android/health: Perform clean up on app unregister call
  android/health: Add HDP SDP record
  android/health: Notify application registration status
  android/health: Notify application deregistration status
  profile/health: Free sdp list after adding it to record

 android/health.c           | 717 ++++++++++++++++++++++++++++++++++++++++++++-
 profiles/health/hdp_util.c |   2 +
 2 files changed, 711 insertions(+), 8 deletions(-)

-- 
1.9.1


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

* [PATCH_v2 1/6] android/health: Cache health application data on app register call
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 2/6] android/health: Perform clean up on app unregister call Ravi kumar Veeramally
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

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

diff --git a/android/health.c b/android/health.c
index 8279f87..4bad7c4 100644
--- a/android/health.c
+++ b/android/health.c
@@ -35,6 +35,8 @@
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
 #include "src/log.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
 
 #include "hal-msg.h"
 #include "ipc-common.h"
@@ -45,10 +47,113 @@
 
 static bdaddr_t adapter_addr;
 static struct ipc *hal_ipc = NULL;
+static struct queue *apps = NULL;
+
+struct mdep_cfg {
+	uint8_t role;
+	uint16_t data_type;
+	uint8_t channel_type;
+	char *descr;
+
+	uint8_t id; /* mdep id */
+};
+
+struct health_app {
+	char *app_name;
+	char *provider_name;
+	char *service_name;
+	char *service_descr;
+	uint8_t num_of_mdep;
+	struct queue *mdeps;
+
+	uint8_t id; /* app id */
+};
+
+static void free_mdep_cfg(void *data)
+{
+	struct mdep_cfg *cfg = data;
+
+	if (!cfg)
+		return;
+
+	free(cfg->descr);
+	free(cfg);
+}
+
+static void free_health_app(void *data)
+{
+	struct health_app *app = data;
+
+	if (!app)
+		return;
+
+	free(app->app_name);
+	free(app->provider_name);
+	free(app->service_name);
+	free(app->service_descr);
+	queue_destroy(app->mdeps, free_mdep_cfg);
+	free(app);
+}
+
+static bool app_by_app_id(const void *data, const void *user_data)
+{
+	const struct health_app *app = data;
+	uint16_t app_id = PTR_TO_INT(user_data);
+
+	return app->id == app_id;
+}
+
+static struct health_app *create_health_app(const char *app_name,
+				const char *provider, const char *srv_name,
+				const char *srv_descr, uint8_t mdeps)
+{
+	struct health_app *app;
+
+	DBG("");
+
+	app = new0(struct health_app, 1);
+	if (!app)
+		return NULL;
+
+	app->id = queue_length(apps) + 1;
+	app->num_of_mdep = mdeps;
+	app->app_name = strdup(app_name);
+
+	if (provider) {
+		app->provider_name = strdup(provider);
+		if (!app->provider_name)
+			goto fail;
+	}
+
+	if (srv_name) {
+		app->service_name = strdup(srv_name);
+		if (!app->service_name)
+			goto fail;
+	}
+
+	if (srv_descr) {
+		app->service_descr = strdup(srv_descr);
+		if (!app->service_descr)
+			goto fail;
+	}
+
+	return app;
+
+fail:
+	free_health_app(app);
+	return NULL;
+}
 
 static void bt_health_register_app(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_health_reg_app *cmd = buf;
+	struct hal_rsp_health_reg_app rsp;
+	struct health_app *app;
+	uint16_t off;
+	uint16_t app_name_len, provider_len, srv_name_len, srv_descr_len;
+	char *app_name, *provider = NULL, *srv_name = NULL, *srv_descr = NULL;
+
+	DBG("");
 
 	if (len != sizeof(*cmd) + cmd->len ||
 			cmd->app_name_off > cmd->provider_name_off ||
@@ -60,18 +165,103 @@ static void bt_health_register_app(const void *buf, uint16_t len)
 		return;
 	}
 
-	DBG("Not implemented");
+	app_name = (char *) cmd->data;
+	app_name_len = cmd->provider_name_off - cmd->app_name_off;
 
-	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_REG_APP,
-							HAL_STATUS_UNSUPPORTED);
+	off = app_name_len;
+	provider_len = cmd->service_name_off - off;
+	if (provider_len > 0)
+		provider = (char *) cmd->data + off;
+
+	off += provider_len;
+	srv_name_len = cmd->service_descr_off - off;
+	if (srv_name_len > 0)
+		srv_name = (char *) cmd->data + off;
+
+	off += srv_name_len;
+	srv_descr_len = cmd->len - off;
+	if (srv_descr_len > 0)
+		srv_descr = (char *) cmd->data + off;
+
+	app = create_health_app(app_name, provider, srv_name, srv_descr,
+							cmd->num_of_mdep);
+
+	if (!queue_push_tail(apps, app))
+		goto fail;
+
+	rsp.app_id = app->id;
+	ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_REG_APP,
+							sizeof(rsp), &rsp, -1);
+	return;
+
+fail:
+	free_health_app(app);
+	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_MDEP,
+							HAL_STATUS_FAILED);
 }
 
 static void bt_health_mdep_cfg_data(const void *buf, uint16_t len)
 {
-	DBG("Not implemented");
+	const struct hal_cmd_health_mdep *cmd = buf;
+	struct health_app *app;
+	struct mdep_cfg *mdep = NULL;
+	uint8_t status;
+
+	DBG("");
+
+	app = queue_find(apps, app_by_app_id, INT_TO_PTR(cmd->app_id));
+	if (!app) {
+		status = HAL_STATUS_INVALID;
+		goto fail;
+	}
+
+	mdep = new0(struct mdep_cfg, 1);
+	if (!mdep) {
+		status = HAL_STATUS_INVALID;
+		goto fail;
+	}
 
+	mdep->role = cmd->role;
+	mdep->data_type = cmd->data_type;
+	mdep->channel_type = cmd->channel_type;
+	mdep->id = queue_length(app->mdeps) + 1;
+
+	if (cmd->descr_len > 0) {
+		mdep->descr = malloc0(cmd->descr_len);
+		memcpy(mdep->descr, cmd->descr, cmd->descr_len);
+	}
+
+	if (app->num_of_mdep > 0 && !app->mdeps) {
+		app->mdeps = queue_new();
+		if (!app->mdeps) {
+			status = HAL_STATUS_FAILED;
+			goto fail;
+		}
+	}
+
+	if (!queue_push_tail(app->mdeps, mdep)) {
+		status = HAL_STATUS_FAILED;
+		goto fail;
+	}
+
+	if (app->num_of_mdep != queue_length(app->mdeps))
+		goto send_rsp;
+
+	/* TODO: Create MCAP instance and prepare SDP profile */
+send_rsp:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_MDEP,
-							HAL_STATUS_UNSUPPORTED);
+							HAL_STATUS_SUCCESS);
+	return;
+
+fail:
+	if (status != HAL_STATUS_SUCCESS) {
+		free_mdep_cfg(mdep);
+		queue_remove(apps, app);
+		free_health_app(app);
+	}
+
+	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_MDEP,
+								status);
 }
 
 static void bt_health_unregister_app(const void *buf, uint16_t len)
@@ -123,6 +313,10 @@ bool bt_health_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 	bacpy(&adapter_addr, addr);
 
 	hal_ipc = ipc;
+	apps = queue_new();
+	if (!apps)
+		return false;
+
 	ipc_register(hal_ipc, HAL_SERVICE_ID_HEALTH, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
 
@@ -133,6 +327,7 @@ void bt_health_unregister(void)
 {
 	DBG("");
 
+	queue_destroy(apps, free_health_app);
 	ipc_unregister(hal_ipc, HAL_SERVICE_ID_HEALTH);
 	hal_ipc = NULL;
 }
-- 
1.9.1


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

* [PATCH_v2 2/6] android/health: Perform clean up on app unregister call
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 1/6] android/health: Cache health application data on app register call Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 3/6] android/health: Add HDP SDP record Ravi kumar Veeramally
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

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

diff --git a/android/health.c b/android/health.c
index 4bad7c4..59a97c0 100644
--- a/android/health.c
+++ b/android/health.c
@@ -266,10 +266,21 @@ fail:
 
 static void bt_health_unregister_app(const void *buf, uint16_t len)
 {
-	DBG("Not implemented");
+	const struct hal_cmd_health_unreg_app *cmd = buf;
+	struct health_app *app;
+
+	DBG("");
+
+	app = queue_remove_if(apps, app_by_app_id, INT_TO_PTR(cmd->app_id));
+	if (!app) {
+		ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH,
+				HAL_OP_HEALTH_UNREG_APP, HAL_STATUS_INVALID);
+		return;
+	}
 
-	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_UNREG_APP,
-							HAL_STATUS_UNSUPPORTED);
+	free_health_app(app);
+	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH,
+				HAL_OP_HEALTH_UNREG_APP, HAL_STATUS_SUCCESS);
 }
 
 static void bt_health_connect_channel(const void *buf, uint16_t len)
-- 
1.9.1


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

* [PATCH_v2 3/6] android/health: Add HDP SDP record
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 1/6] android/health: Cache health application data on app register call Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 2/6] android/health: Perform clean up on app unregister call Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 4/6] android/health: Notify application registration status Ravi kumar Veeramally
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

SDP record preparation code copied from profiles/health/hdp_uitl.c.
So applying GSyC copyrights.
---
 android/health.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 479 insertions(+), 1 deletion(-)

diff --git a/android/health.c b/android/health.c
index 59a97c0..3029439 100644
--- a/android/health.c
+++ b/android/health.c
@@ -3,6 +3,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
  *
  *
  *  This library is free software; you can redistribute it and/or
@@ -31,6 +32,7 @@
 #include <unistd.h>
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
@@ -44,10 +46,18 @@
 #include "utils.h"
 #include "bluetooth.h"
 #include "health.h"
+#include "mcap-lib.h"
+
+#define SVC_HINT_HEALTH			0x00
+#define HDP_VERSION			0x0101
+#define DATA_EXCHANGE_SPEC_11073	0x01
 
 static bdaddr_t adapter_addr;
 static struct ipc *hal_ipc = NULL;
 static struct queue *apps = NULL;
+static struct mcap_instance *mcap = NULL;
+static uint32_t record_id = 0;
+static uint32_t record_state = 0;
 
 struct mdep_cfg {
 	uint8_t role;
@@ -95,6 +105,14 @@ static void free_health_app(void *data)
 	free(app);
 }
 
+static bool mdep_by_mdep_role(const void *data, const void *user_data)
+{
+	const struct mdep_cfg *mdep = data;
+	uint16_t role = PTR_TO_INT(user_data);
+
+	return mdep->role == role;
+}
+
 static bool app_by_app_id(const void *data, const void *user_data)
 {
 	const struct health_app *app = data;
@@ -103,6 +121,413 @@ static bool app_by_app_id(const void *data, const void *user_data)
 	return app->id == app_id;
 }
 
+static int register_service_protocols(sdp_record_t *rec,
+					struct health_app *app)
+{
+	uuid_t l2cap_uuid, mcap_c_uuid;
+	sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
+	sdp_list_t *access_proto_list = NULL;
+	sdp_data_t *psm = NULL, *mcap_ver = NULL;
+	uint32_t ccpsm;
+	uint16_t version = MCAP_VERSION;
+	GError *err = NULL;
+	int ret = -1;
+
+	DBG("");
+
+	/* set l2cap information */
+	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+	l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
+	if (!l2cap_list)
+		goto fail;
+
+	ccpsm = mcap_get_ctrl_psm(mcap, &err);
+	if (err)
+		goto fail;
+
+	psm = sdp_data_alloc(SDP_UINT16, &ccpsm);
+	if (!psm)
+		goto fail;
+
+	if (!sdp_list_append(l2cap_list, psm))
+		goto fail;
+
+	proto_list = sdp_list_append(NULL, l2cap_list);
+	if (!proto_list)
+		goto fail;
+
+	/* set mcap information */
+	sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID);
+	mcap_list = sdp_list_append(NULL, &mcap_c_uuid);
+	if (!mcap_list)
+		goto fail;
+
+	mcap_ver = sdp_data_alloc(SDP_UINT16, &version);
+	if (!mcap_ver)
+		goto fail;
+
+	if (!sdp_list_append(mcap_list, mcap_ver))
+		goto fail;
+
+	if (!sdp_list_append(proto_list, mcap_list))
+		goto fail;
+
+	/* attach protocol information to service record */
+	access_proto_list = sdp_list_append(NULL, proto_list);
+	if (!access_proto_list)
+		goto fail;
+
+	sdp_set_access_protos(rec, access_proto_list);
+	ret = 0;
+
+fail:
+	sdp_list_free(l2cap_list, NULL);
+	sdp_list_free(mcap_list, NULL);
+	sdp_list_free(proto_list, NULL);
+	sdp_list_free(access_proto_list, NULL);
+
+	if (psm)
+		sdp_data_free(psm);
+
+	if (mcap_ver)
+		sdp_data_free(mcap_ver);
+
+	if (err)
+		g_error_free(err);
+
+	return ret;
+}
+
+static int register_service_profiles(sdp_record_t *rec)
+{
+	int ret;
+	sdp_list_t *profile_list;
+	sdp_profile_desc_t hdp_profile;
+
+	DBG("");
+
+	/* set hdp information */
+	sdp_uuid16_create(&hdp_profile.uuid, HDP_SVCLASS_ID);
+	hdp_profile.version = HDP_VERSION;
+	profile_list = sdp_list_append(NULL, &hdp_profile);
+	if (!profile_list)
+		return -1;
+
+	/* set profile descriptor list */
+	ret = sdp_set_profile_descs(rec, profile_list);
+	sdp_list_free(profile_list, NULL);
+
+	return ret;
+}
+
+static int register_service_additional_protocols(sdp_record_t *rec,
+						struct health_app *app)
+{
+	int ret = -1;
+	uuid_t l2cap_uuid, mcap_d_uuid;
+	sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
+	sdp_list_t *access_proto_list = NULL;
+	sdp_data_t *psm = NULL;
+	uint32_t dcpsm;
+	GError *err;
+
+	DBG("");
+
+	/* set l2cap information */
+	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+	l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
+	if (!l2cap_list)
+		goto fail;
+
+	dcpsm = mcap_get_ctrl_psm(mcap, &err);
+	if (err)
+		goto fail;
+
+	psm = sdp_data_alloc(SDP_UINT16, &dcpsm);
+	if (!psm)
+		goto fail;
+
+	if (!sdp_list_append(l2cap_list, psm))
+		goto fail;
+
+	proto_list = sdp_list_append(NULL, l2cap_list);
+	if (!proto_list)
+		goto fail;
+
+	/* set mcap information */
+	sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID);
+	mcap_list = sdp_list_append(NULL, &mcap_d_uuid);
+	if (!mcap_list)
+		goto fail;
+
+	if (!sdp_list_append(proto_list, mcap_list))
+		goto fail;
+
+	/* attach protocol information to service record */
+	access_proto_list = sdp_list_append(NULL, proto_list);
+	if (!access_proto_list)
+		goto fail;
+
+	sdp_set_add_access_protos(rec, access_proto_list);
+	ret = 0;
+
+fail:
+	sdp_list_free(l2cap_list, NULL);
+	sdp_list_free(mcap_list, NULL);
+	sdp_list_free(proto_list, NULL);
+	sdp_list_free(access_proto_list, NULL);
+
+	if (psm)
+		sdp_data_free(psm);
+
+	if (err)
+		g_error_free(err);
+
+	return ret;
+}
+
+static sdp_list_t *mdeps_to_sdp_features(struct mdep_cfg *mdep)
+{
+	sdp_data_t *mdepid, *dtype = NULL, *role = NULL, *descr = NULL;
+	sdp_list_t *f_list = NULL;
+
+	DBG("");
+
+	mdepid = sdp_data_alloc(SDP_UINT8, &mdep->id);
+	if (!mdepid)
+		return NULL;
+
+	dtype = sdp_data_alloc(SDP_UINT16, &mdep->data_type);
+	if (!dtype)
+		goto fail;
+
+	role = sdp_data_alloc(SDP_UINT8, &mdep->role);
+	if (!role)
+		goto fail;
+
+	if (mdep->descr) {
+		descr = sdp_data_alloc(SDP_TEXT_STR8, mdep->descr);
+		if (!descr)
+			goto fail;
+	}
+
+	f_list = sdp_list_append(NULL, mdepid);
+	if (!f_list)
+		goto fail;
+
+	if (!sdp_list_append(f_list, dtype))
+		goto fail;
+
+	if (!sdp_list_append(f_list, role))
+		goto fail;
+
+	if (descr && !sdp_list_append(f_list, descr))
+		goto fail;
+
+	return f_list;
+
+fail:
+	sdp_list_free(f_list, NULL);
+
+	if (mdepid)
+		sdp_data_free(mdepid);
+
+	if (dtype)
+		sdp_data_free(dtype);
+
+	if (role)
+		sdp_data_free(role);
+
+	if (descr)
+		sdp_data_free(descr);
+
+	return NULL;
+}
+
+static void free_hdp_list(void *list)
+{
+	sdp_list_t *hdp_list = list;
+
+	sdp_list_free(hdp_list, (sdp_free_func_t)sdp_data_free);
+	hdp_list = NULL;
+}
+
+static void register_features(void *data, void *user_data)
+{
+	struct mdep_cfg *mdep = data;
+	sdp_list_t **sup_features = user_data;
+	sdp_list_t *hdp_feature;
+
+	DBG("");
+
+	hdp_feature = mdeps_to_sdp_features(mdep);
+	if (!hdp_feature)
+		return;
+
+	if (!*sup_features) {
+		*sup_features = sdp_list_append(NULL, hdp_feature);
+		if (!*sup_features)
+			sdp_list_free(hdp_feature,
+					(sdp_free_func_t)sdp_data_free);
+	} else if (!sdp_list_append(*sup_features, hdp_feature)) {
+		sdp_list_free(hdp_feature,
+					(sdp_free_func_t)sdp_data_free);
+	}
+}
+
+static int register_service_sup_features(sdp_record_t *rec,
+						struct health_app *app)
+{
+	sdp_list_t *sup_features = NULL;
+
+	DBG("");
+
+	queue_foreach(app->mdeps, register_features, &sup_features);
+	if (!sup_features)
+		return -1;
+
+	if (sdp_set_supp_feat(rec, sup_features) < 0) {
+		sdp_list_free(sup_features, free_hdp_list);
+		return -1;
+	}
+
+	sdp_list_free(sup_features, free_hdp_list);
+	return 0;
+}
+
+static int register_data_exchange_spec(sdp_record_t *rec)
+{
+	sdp_data_t *spec;
+	uint8_t data_spec = DATA_EXCHANGE_SPEC_11073;
+	/* As of now only 11073 is supported, so we set it as default */
+
+	DBG("");
+
+	spec = sdp_data_alloc(SDP_UINT8, &data_spec);
+	if (!spec)
+		return -1;
+
+	if (sdp_attr_add(rec, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) {
+		sdp_data_free(spec);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int register_mcap_features(sdp_record_t *rec)
+{
+	sdp_data_t *mcap_proc;
+	uint8_t mcap_sup_proc = MCAP_SUP_PROC;
+
+	DBG("");
+
+	mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc);
+	if (!mcap_proc)
+		return -1;
+
+	if (sdp_attr_add(rec, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES,
+							mcap_proc) < 0) {
+		sdp_data_free(mcap_proc);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int set_sdp_services_uuid(sdp_record_t *rec, uint8_t role)
+{
+	uuid_t source, sink;
+	sdp_list_t *list = NULL;
+
+	sdp_uuid16_create(&sink, HDP_SINK_SVCLASS_ID);
+	sdp_uuid16_create(&source, HDP_SOURCE_SVCLASS_ID);
+	sdp_get_service_classes(rec, &list);
+
+	switch (role) {
+	case HAL_HEALTH_MDEP_ROLE_SOURCE:
+		if (!sdp_list_find(list, &source, sdp_uuid_cmp))
+			list = sdp_list_append(list, &source);
+		break;
+	case HAL_HEALTH_MDEP_ROLE_SINK:
+		if (!sdp_list_find(list, &sink, sdp_uuid_cmp))
+			list = sdp_list_append(list, &sink);
+		break;
+	}
+
+	if (sdp_set_service_classes(rec, list) < 0) {
+		sdp_list_free(list, NULL);
+		return -1;
+	}
+
+	sdp_list_free(list, NULL);
+
+	return 0;
+}
+
+static int update_sdp_record(struct health_app *app)
+{
+	sdp_record_t *rec;
+	uint8_t role;
+
+	DBG("");
+
+	if (record_id > 0) {
+		bt_adapter_remove_record(record_id);
+		record_id = 0;
+	}
+
+	rec = sdp_record_alloc();
+	if (!rec)
+		return -1;
+
+	role = HAL_HEALTH_MDEP_ROLE_SOURCE;
+	if (queue_find(app->mdeps, mdep_by_mdep_role, INT_TO_PTR(role)))
+		set_sdp_services_uuid(rec, role);
+
+	role = HAL_HEALTH_MDEP_ROLE_SINK;
+	if (queue_find(app->mdeps, mdep_by_mdep_role, INT_TO_PTR(role)))
+		set_sdp_services_uuid(rec, role);
+
+	sdp_set_info_attr(rec, app->service_name, app->provider_name,
+							app->service_descr);
+
+	if (register_service_protocols(rec, app) < 0)
+		goto fail;
+
+	if (register_service_profiles(rec) < 0)
+		goto fail;
+
+	if (register_service_additional_protocols(rec, app) < 0)
+		goto fail;
+
+	if (register_service_sup_features(rec, app) < 0)
+		goto fail;
+
+	if (register_data_exchange_spec(rec) < 0)
+		goto fail;
+
+	if (register_mcap_features(rec) < 0)
+		goto fail;
+
+	if (sdp_set_record_state(rec, record_state++) < 0)
+		goto fail;
+
+	if (bt_adapter_add_record(rec, SVC_HINT_HEALTH) < 0) {
+		error("Failed to register HEALTH record");
+		goto fail;
+	}
+
+	record_id = rec->handle;
+
+	return 0;
+
+fail:
+	sdp_record_free(rec);
+
+	return -1;
+}
+
 static struct health_app *create_health_app(const char *app_name,
 				const char *provider, const char *srv_name,
 				const char *srv_descr, uint8_t mdeps)
@@ -247,7 +672,20 @@ static void bt_health_mdep_cfg_data(const void *buf, uint16_t len)
 	if (app->num_of_mdep != queue_length(app->mdeps))
 		goto send_rsp;
 
-	/* TODO: Create MCAP instance and prepare SDP profile */
+	/* add sdp record from app configuration data */
+	/*
+	 * TODO: Check what to be done if mupltple applications are trying to
+	 * register with different role and different configurations.
+	 * 1) Does device supports SOURCE and SINK at the same time ?
+	 * 2) Does it require different SDP records or one record with
+	 *    multile MDEP configurations ?
+	 */
+	if (update_sdp_record(app) < 0) {
+		error("Error creating HDP SDP record");
+		status = HAL_STATUS_FAILED;
+		goto fail;
+	}
+
 send_rsp:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_MDEP,
 							HAL_STATUS_SUCCESS);
@@ -278,6 +716,11 @@ static void bt_health_unregister_app(const void *buf, uint16_t len)
 		return;
 	}
 
+	if (record_id > 0) {
+		bt_adapter_remove_record(record_id);
+		record_id = 0;
+	}
+
 	free_health_app(app);
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH,
 				HAL_OP_HEALTH_UNREG_APP, HAL_STATUS_SUCCESS);
@@ -317,12 +760,46 @@ static const struct ipc_handler cmd_handlers[] = {
 				sizeof(struct hal_cmd_health_destroy_channel) },
 };
 
+static void mcl_connected(struct mcap_mcl *mcl, gpointer data)
+{
+	DBG("Not implemented");
+}
+
+static void mcl_reconnected(struct mcap_mcl *mcl, gpointer data)
+{
+	DBG("Not implemented");
+}
+
+static void mcl_disconnected(struct mcap_mcl *mcl, gpointer data)
+{
+	DBG("Not implemented");
+}
+
+static void mcl_uncached(struct mcap_mcl *mcl, gpointer data)
+{
+	DBG("Not implemented");
+}
+
 bool bt_health_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
+	GError *err = NULL;
+
 	DBG("");
 
 	bacpy(&adapter_addr, addr);
 
+	mcap = mcap_create_instance(&adapter_addr, BT_IO_SEC_MEDIUM, 0, 0,
+					mcl_connected, mcl_reconnected,
+					mcl_disconnected, mcl_uncached,
+					NULL, /* CSP is not used right now */
+					NULL, &err);
+
+	if (!mcap) {
+		error("Error creating MCAP instance : %s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
 	hal_ipc = ipc;
 	apps = queue_new();
 	if (!apps)
@@ -338,6 +815,7 @@ void bt_health_unregister(void)
 {
 	DBG("");
 
+	mcap_instance_unref(mcap);
 	queue_destroy(apps, free_health_app);
 	ipc_unregister(hal_ipc, HAL_SERVICE_ID_HEALTH);
 	hal_ipc = NULL;
-- 
1.9.1


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

* [PATCH_v2 4/6] android/health: Notify application registration status
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
                   ` (2 preceding siblings ...)
  2014-06-16 15:01 ` [PATCH_v2 3/6] android/health: Add HDP SDP record Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 5/6] android/health: Notify application deregistration status Ravi kumar Veeramally
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

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

diff --git a/android/health.c b/android/health.c
index 3029439..4862b76 100644
--- a/android/health.c
+++ b/android/health.c
@@ -105,6 +105,19 @@ static void free_health_app(void *data)
 	free(app);
 }
 
+static void send_app_reg_notify(struct health_app *app, uint8_t state)
+{
+	struct hal_ev_health_app_reg_state ev;
+
+	DBG("");
+
+	ev.id = app->id;
+	ev.state = state;
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HEALTH,
+				HAL_EV_HEALTH_APP_REG_STATE, sizeof(ev), &ev);
+}
+
 static bool mdep_by_mdep_role(const void *data, const void *user_data)
 {
 	const struct mdep_cfg *mdep = data;
@@ -686,6 +699,8 @@ static void bt_health_mdep_cfg_data(const void *buf, uint16_t len)
 		goto fail;
 	}
 
+	send_app_reg_notify(app, HAL_HEALTH_APP_REG_SUCCESS);
+
 send_rsp:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_OP_HEALTH_MDEP,
 							HAL_STATUS_SUCCESS);
-- 
1.9.1


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

* [PATCH_v2 5/6] android/health: Notify application deregistration status
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
                   ` (3 preceding siblings ...)
  2014-06-16 15:01 ` [PATCH_v2 4/6] android/health: Notify application registration status Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 15:01 ` [PATCH_v2 6/6] profile/health: Free sdp list after adding it to record Ravi kumar Veeramally
  2014-06-16 16:41 ` [PATCH_v2 0/6] HDP initial implementaion Szymon Janc
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

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

diff --git a/android/health.c b/android/health.c
index 4862b76..36ed6e7 100644
--- a/android/health.c
+++ b/android/health.c
@@ -731,6 +731,8 @@ static void bt_health_unregister_app(const void *buf, uint16_t len)
 		return;
 	}
 
+	send_app_reg_notify(app, HAL_HEALTH_APP_DEREG_SUCCESS);
+
 	if (record_id > 0) {
 		bt_adapter_remove_record(record_id);
 		record_id = 0;
-- 
1.9.1


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

* [PATCH_v2 6/6] profile/health: Free sdp list after adding it to record
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
                   ` (4 preceding siblings ...)
  2014-06-16 15:01 ` [PATCH_v2 5/6] android/health: Notify application deregistration status Ravi kumar Veeramally
@ 2014-06-16 15:01 ` Ravi kumar Veeramally
  2014-06-16 16:41 ` [PATCH_v2 0/6] HDP initial implementaion Szymon Janc
  6 siblings, 0 replies; 8+ messages in thread
From: Ravi kumar Veeramally @ 2014-06-16 15:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

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

diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c
index 58770b5..47c464e 100644
--- a/profiles/health/hdp_util.c
+++ b/profiles/health/hdp_util.c
@@ -652,6 +652,8 @@ static gboolean register_service_sup_features(GSList *app_list,
 		return FALSE;
 	}
 
+	sdp_list_free(sup_features, free_hdp_list);
+
 	return TRUE;
 }
 
-- 
1.9.1


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

* Re: [PATCH_v2 0/6] HDP initial implementaion
  2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
                   ` (5 preceding siblings ...)
  2014-06-16 15:01 ` [PATCH_v2 6/6] profile/health: Free sdp list after adding it to record Ravi kumar Veeramally
@ 2014-06-16 16:41 ` Szymon Janc
  6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-06-16 16:41 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth

Hi Ravi,

On Monday 16 June 2014 18:01:34 Ravi kumar Veeramally wrote:
> v2: Fixed comments from Szymon (optimized cache patch,
>     split notify patch, other issues).
> v1: Fixed comments from szymon.
> 
> RFC_v2: Fixed comments by szymon and fixed issues while sebastian
> testing with PTS.
> 
> RFC_v1: patchset is initial implementaion for HDP at daemon side.
> Cacheing application data and prepare SDP record based on MDEPs
> configuration and notify app state.
> 
> Ravi kumar Veeramally (6):
>   android/health: Cache health application data on app register call
>   android/health: Perform clean up on app unregister call
>   android/health: Add HDP SDP record
>   android/health: Notify application registration status
>   android/health: Notify application deregistration status
>   profile/health: Free sdp list after adding it to record
> 
>  android/health.c           | 717
> ++++++++++++++++++++++++++++++++++++++++++++- profiles/health/hdp_util.c | 
>  2 +
>  2 files changed, 711 insertions(+), 8 deletions(-)

Patches 1-5 are now applied (with changes we discussed on IRC), thanks.

-- 
Szymon K. Janc
szymon.janc@gmail.com

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

end of thread, other threads:[~2014-06-16 16:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-16 15:01 [PATCH_v2 0/6] HDP initial implementaion Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 1/6] android/health: Cache health application data on app register call Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 2/6] android/health: Perform clean up on app unregister call Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 3/6] android/health: Add HDP SDP record Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 4/6] android/health: Notify application registration status Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 5/6] android/health: Notify application deregistration status Ravi kumar Veeramally
2014-06-16 15:01 ` [PATCH_v2 6/6] profile/health: Free sdp list after adding it to record Ravi kumar Veeramally
2014-06-16 16:41 ` [PATCH_v2 0/6] HDP initial implementaion Szymon Janc

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