From: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
To: Szymon Janc <szymon.janc@gmail.com>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH 3/4] android/health: Initial connect channel implementation
Date: Mon, 16 Jun 2014 23:57:08 +0300 [thread overview]
Message-ID: <539F5A24.6060806@linux.intel.com> (raw)
In-Reply-To: <14926635.zyrbEXOCF2@athlon>
Hi Szymon,
On 06/16/2014 11:21 PM, Szymon Janc wrote:
> Hi Ravi,
>
> On Monday 16 June 2014 20:51:13 Ravi kumar Veeramally wrote:
>> Fetches remote sdp record and initiates MCL connection.
>> ---
>> android/health.c | 416
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 414
>> insertions(+), 2 deletions(-)
>>
>> diff --git a/android/health.c b/android/health.c
>> index 7e2c5d6..07df2c4 100644
>> --- a/android/health.c
>> +++ b/android/health.c
>> @@ -36,9 +36,13 @@
>> #include "lib/bluetooth.h"
>> #include "lib/sdp.h"
>> #include "lib/sdp_lib.h"
>> +#include "lib/uuid.h"
>> +#include "lib/l2cap.h"
>> #include "src/log.h"
>> #include "src/shared/util.h"
>> #include "src/shared/queue.h"
>> +#include "src/uuid-helper.h"
>> +#include "src/sdp-client.h"
>>
>> #include "hal-msg.h"
>> #include "ipc-common.h"
>> @@ -59,6 +63,17 @@ static struct mcap_instance *mcap = NULL;
>> static uint32_t record_id = 0;
>> static uint32_t record_state = 0;
>>
>> +struct health_device;
>> +
> Reorder structures definitions to avoid this.
Ok.
>
>> +struct health_channel {
>> + uint8_t mdep_id;
>> + uint8_t type;
>> +
>> + struct health_device *dev;
>> +
>> + uint16_t id; /* channel id */
>> +};
>> +
>> struct mdep_cfg {
>> uint8_t role;
>> uint16_t data_type;
>> @@ -68,6 +83,19 @@ struct mdep_cfg {
>> uint8_t id; /* mdep id */
>> };
>>
>> +struct health_device {
>> + bdaddr_t dst;
>> + uint16_t app_id;
>> +
>> + struct mcap_mcl *mcl;
>> + bool mcl_conn;
>> +
>> + struct queue *channels; /* data channels */
>> +
>> + uint16_t ccpsm;
>> + uint16_t dcpsm;
>> +};
>> +
>> struct health_app {
>> char *app_name;
>> char *provider_name;
>> @@ -77,8 +105,54 @@ struct health_app {
>> struct queue *mdeps;
>>
>> uint16_t id; /* app id */
>> + struct queue *devices;
>> };
>>
>> +static void free_health_channel(void *data)
>> +{
>> + struct health_channel *channel = data;
>> +
>> + if (!channel)
>> + return;
>> +
>> + free(channel);
>> +}
>> +
>> +static void destroy_channel(void *data)
>> +{
>> + struct health_channel *channel = data;
>> +
>> + if (!channel)
>> + return;
>> +
>> + /* TODO: Notify channel connection status DESTROYED */
>> + queue_remove(channel->dev->channels, channel);
>> + free_health_channel(channel);
>> +}
>> +
>> +static void unref_mcl(struct health_device *dev)
>> +{
>> + if (!dev && !dev->mcl)
>> + return;
>> +
>> + mcap_close_mcl(dev->mcl, FALSE);
>> + mcap_mcl_unref(dev->mcl);
>> + dev->mcl = NULL;
>> + dev->mcl_conn = FALSE;
>> +}
>> +
>> +static void free_health_device(void *data)
>> +{
>> + struct health_device *dev = data;
>> +
>> + if (!dev)
>> + return;
>> +
>> + unref_mcl(dev);
>> + queue_destroy(dev->channels, free_health_channel);
>> + free(dev);
>> +}
>> +
>> static void free_mdep_cfg(void *data)
>> {
>> struct mdep_cfg *cfg = data;
>> @@ -102,6 +176,7 @@ static void free_health_app(void *data)
>> free(app->service_name);
>> free(app->service_descr);
>> queue_destroy(app->mdeps, free_mdep_cfg);
>> + queue_destroy(app->devices, free_health_device);
>> free(app);
>> }
>>
>> @@ -126,6 +201,14 @@ static bool mdep_by_mdep_role(const void *data, const
>> void *user_data) return mdep->role == role;
>> }
>>
>> +static bool mdep_by_mdep_id(const void *data, const void *user_data)
>> +{
>> + const struct mdep_cfg *mdep = data;
>> + uint16_t mdep_id = PTR_TO_INT(user_data);
>> +
>> + return mdep->id == mdep_id;
>> +}
>> +
>> static bool app_by_app_id(const void *data, const void *user_data)
>> {
>> const struct health_app *app = data;
>> @@ -744,12 +827,341 @@ static void bt_health_unregister_app(const void *buf,
>> uint16_t len) HAL_OP_HEALTH_UNREG_APP, HAL_STATUS_SUCCESS);
>> }
>>
>> +static int get_prot_desc_entry(sdp_data_t *entry, int type, guint16 *val)
>> +{
>> + sdp_data_t *iter;
>> + int proto;
>> +
>> + if (!entry || !SDP_IS_SEQ(entry->dtd))
>> + return -1;
>> +
>> + iter = entry->val.dataseq;
>> + if (!(iter->dtd & SDP_UUID_UNSPEC))
>> + return -1;
>> + proto = sdp_uuid_to_proto(&iter->val.uuid);
>> + if (proto != type)
>> + return -1;
>> +
>> + if (!val)
>> + return 0;
>> +
>> + iter = iter->next;
>> + if (iter->dtd != SDP_UINT16)
>> + return -1;
>> +
>> + *val = iter->val.uint16;
>> +
>> + return 0;
>> +}
>> +
>> +static int get_prot_desc_list(const sdp_record_t *rec, uint16_t *psm,
>> + uint16_t *version)
>> +{
>> + sdp_data_t *pdl, *p0, *p1;
>> +
>> + if (!psm && !version)
>> + return -1;
>> +
>> + pdl = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
>> + if (!pdl || !SDP_IS_SEQ(pdl->dtd))
>> + return -1;
>> +
>> + p0 = pdl->val.dataseq;
>> + if (get_prot_desc_entry(p0, L2CAP_UUID, psm) < 0)
>> + return -1;
>> +
>> + p1 = p0->next;
>> + if (get_prot_desc_entry(p1, MCAP_CTRL_UUID, version) < 0)
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +static int get_ccpsm(sdp_list_t *recs, uint16_t *ccpsm)
>> +{
>> + sdp_list_t *l;
>> +
>> + for (l = recs; l; l = l->next) {
>> + sdp_record_t *rec = l->data;
>> +
>> + if (!get_prot_desc_list(rec, ccpsm, NULL))
>> + return 0;
>> + }
>> +
>> + return -1;
>> +}
>> +
>> +static int get_add_prot_desc_list(const sdp_record_t *rec, uint16_t *psm)
>> +{
>> + sdp_data_t *pdl, *p0, *p1;
>> +
>> + if (!psm)
>> + return -1;
>> +
>> + pdl = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
>> + if (!pdl || pdl->dtd != SDP_SEQ8)
>> + return -1;
>> +
>> + pdl = pdl->val.dataseq;
>> + if (pdl->dtd != SDP_SEQ8)
>> + return -1;
>> +
>> + p0 = pdl->val.dataseq;
>> +
>> + if (get_prot_desc_entry(p0, L2CAP_UUID, psm) < 0)
>> + return -1;
>> +
>> + p1 = p0->next;
>> + if (get_prot_desc_entry(p1, MCAP_DATA_UUID, NULL) < 0)
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +static int get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm)
>> +{
>> + sdp_list_t *l;
>> +
>> + for (l = recs; l; l = l->next) {
>> + sdp_record_t *rec = l->data;
>> +
>> + if (!get_add_prot_desc_list(rec, dcpsm))
>> + return 0;
>> + }
>> +
>> + return -1;
>> +}
>> +
>> +static void mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void mcap_mdl_closed_cb(struct mcap_mdl *mdl, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void mcap_mdl_deleted_cb(struct mcap_mdl *mdl, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void mcap_mdl_aborted_cb(struct mcap_mdl *mdl, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
>> + uint16_t mdlid, uint8_t *conf, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void mcap_mdl_reconn_req_cb(struct mcap_mdl *mdl, void *data)
>> +{
>> + DBG("Not Implemeneted");
>> +}
>> +
>> +static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data)
>> +{
>> + struct health_channel *channel = data;
>> + gboolean ret;
>> + GError *gerr = NULL;
>> +
>> + DBG("");
>> +
>> + if (err) {
>> + error("error creating MCL : %s", err->message);
>> + goto fail;
>> + }
>> +
>> + if (!channel->dev->mcl)
>> + channel->dev->mcl = mcap_mcl_ref(mcl);
>> +
>> + channel->dev->mcl_conn = TRUE;
>> + DBG("MCL connected");
>> +
>> + ret = mcap_mcl_set_cb(channel->dev->mcl, channel, &gerr,
>> + MCAP_MDL_CB_CONNECTED, mcap_mdl_connected_cb,
>> + MCAP_MDL_CB_CLOSED, mcap_mdl_closed_cb,
>> + MCAP_MDL_CB_DELETED, mcap_mdl_deleted_cb,
>> + MCAP_MDL_CB_ABORTED, mcap_mdl_aborted_cb,
>> + MCAP_MDL_CB_REMOTE_CONN_REQ, mcap_mdl_conn_req_cb,
>> + MCAP_MDL_CB_REMOTE_RECONN_REQ, mcap_mdl_reconn_req_cb,
>> + MCAP_MDL_CB_INVALID);
>> + if (!ret) {
>> + error("error setting mdl callbacks on mcl");
>> + goto fail;
>> + }
>> +
>> + /* TODO : create mdl */
>> + return;
>> +
>> +fail:
>> + destroy_channel(channel);
>> +
>> + if (err)
>> + g_error_free(err);
>> +}
>> +
>> +static void search_cb(sdp_list_t *recs, int err, gpointer data)
>> +{
>> + struct health_channel *channel = data;
>> + GError *gerr = NULL;
>> +
>> + DBG("");
>> +
>> + if (err < 0 || !recs) {
>> + error("Error getting remote SDP records");
>> + goto fail;
>> + }
>> +
>> + if (get_ccpsm(recs, &channel->dev->ccpsm) < 0) {
>> + error("Can't get remote PSM for control channel");
>> + goto fail;
>> + }
>> +
>> + if (get_dcpsm(recs, &channel->dev->dcpsm) < 0) {
>> + error("Can't get remote PSM for data channel");
>> + goto fail;
>> + }
>> +
>> + if (!mcap_create_mcl(mcap, &channel->dev->dst, channel->dev->ccpsm,
>> + create_mcl_cb, channel, NULL, &gerr)) {
>> + error("error creating mcl %s", gerr->message);
>> + goto fail;
>> + }
>> +
>> + /* TODO: send channel state CONNECTING */
>> + return;
>> +
>> +fail:
>> + /* TODO: send channel state DESTROYED*/
>> +
>> + queue_remove(channel->dev->channels, channel);
>> + free_health_channel(channel);
>> +
>> + if (gerr)
>> + g_error_free(gerr);
>> +}
>> +
>> +static int connect_mcl(struct health_channel *channel)
>> +{
>> + uuid_t uuid;
>> +
>> + DBG("");
>> +
>> + bt_string2uuid(&uuid, HDP_UUID);
>> +
>> + return bt_search_service(&adapter_addr, &channel->dev->dst, &uuid,
>> + search_cb, channel, NULL, 0);
>> +}
>> +
>> +static struct health_device *create_device(
>> + const struct hal_cmd_health_connect_channel *cmd)
> I'd avoid passing hal structs to helpers and just pass bdaddr and app_id to
> this helper.
Ok.
>> +{
>> + struct health_device *dev;
>> +
>> + dev = new0(struct health_device, 1);
>> + if (!dev)
>> + return NULL;
>> +
>> + android2bdaddr(&cmd->bdaddr, &dev->dst);
>> + dev->app_id = cmd->app_id;
>> +
>> + return dev;
>> +}
>> +
>> +static struct health_channel *create_channel(uint8_t app_id, uint8_t
>> mdep_index) +{
>> + struct health_app *app;
>> + struct mdep_cfg *mdep;
>> + struct health_channel *channel;
>> + uint8_t index;
>> + static unsigned int channel_id = 1;
>> +
>> + app = queue_find(apps, app_by_app_id, INT_TO_PTR(app_id));
>> + if (!app)
>> + return NULL;
>> +
>> + index = mdep_index + 1;
>> + mdep = queue_find(app->mdeps, mdep_by_mdep_id, INT_TO_PTR(index));
>> + if (!mdep)
>> + return NULL;
>> +
>> + channel = new0(struct health_channel, 1);
>> + if (!channel)
>> + return NULL;
>> +
>> + channel->mdep_id = mdep_index;
>> + channel->type = mdep->channel_type;
>> + channel->id = channel_id++;
>> +
>> + return channel;
>> +}
>> +
>> static void bt_health_connect_channel(const void *buf, uint16_t len)
>> {
>> - DBG("Not implemented");
>> + const struct hal_cmd_health_connect_channel *cmd = buf;
>> + struct hal_rsp_health_connect_channel rsp;
>> + struct health_app *app;
>> + struct health_device *dev = NULL;
>> + struct health_channel *channel = NULL;
>> +
>> + DBG("");
>>
>> + app = queue_find(apps, app_by_app_id, INT_TO_PTR(cmd->app_id));
>> + if (!app)
>> + goto fail;
>> +
>> + dev = create_device(cmd);
>> + if (!dev)
>> + goto fail;
>> +
>> + channel = create_channel(cmd->app_id, cmd->mdep_index);
>> + if (!channel)
>> + goto fail;
>> +
>> + channel->dev = dev;
>> +
>> + if (!app->devices) {
>> + app->devices = queue_new();
>> + if (!app->devices)
>> + goto fail;
>> + }
>> +
>> + if (!queue_push_tail(app->devices, dev))
>> + goto fail;
>> +
>> + if (!dev->channels) {
>> + dev->channels = queue_new();
>> + if (!dev->channels)
>> + goto fail;
>> + }
>> +
>> + if (!queue_push_tail(dev->channels, channel)) {
>> + queue_remove(app->devices, dev);
>> + goto fail;
>> + }
>> +
>> + if (connect_mcl(channel) < 0) {
>> + error("error retrieving HDP SDP record");
>> + queue_remove(app->devices, dev);
>> + goto fail;
>> + }
>> +
>> + rsp.channel_id = channel->id;
>> + ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_HEALTH,
>> + HAL_OP_HEALTH_CONNECT_CHANNEL,
>> + sizeof(rsp), &rsp, -1);
>> + return;
>> +
>> +fail:
>> + free_health_channel(channel);
>> + free_health_device(dev);
>> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HEALTH,
>> - HAL_OP_HEALTH_CONNECT_CHANNEL, HAL_STATUS_UNSUPPORTED);
>> + HAL_OP_HEALTH_CONNECT_CHANNEL, HAL_STATUS_FAILED);
>> }
>>
>> static void bt_health_destroy_channel(const void *buf, uint16_t len)
Thanks,
Ravi.
next prev parent reply other threads:[~2014-06-16 20:57 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-16 17:51 [PATCH 0/4] Intiates L2CAP Control Channel Ravi kumar Veeramally
2014-06-16 17:51 ` [PATCH 1/4] profiles/health/hdp: Fix memory leak in SDP record preparati Sdp record preparation part is copied to android/health.c from profiles/health/hdp_utils.c. Memory leak is noticed while testing. Memory summay is from android daemon, but code snippet is same. It is already fixed in android/health.c while submitting android related patches Ravi kumar Veeramally
2014-06-16 17:51 ` [PATCH 2/4] anrdoid/hal-health: Fix wrong channel type defines Ravi kumar Veeramally
2014-06-16 20:16 ` Szymon Janc
2014-06-16 20:56 ` Ravi kumar Veeramally
2014-06-16 17:51 ` [PATCH 3/4] android/health: Initial connect channel implementation Ravi kumar Veeramally
2014-06-16 20:21 ` Szymon Janc
2014-06-16 20:57 ` Ravi kumar Veeramally [this message]
2014-06-16 17:51 ` [PATCH 4/4] android/health: Notify channel connection status Ravi kumar Veeramally
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=539F5A24.6060806@linux.intel.com \
--to=ravikumar.veeramally@linux.intel.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=szymon.janc@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.