Diff between d0b936a26c09065a9568e4593965a3ea6ce476d9 and 147049dac962a4a8698fa70a9eb45203100817a3

Changed Files

File Additions Deletions Status
android/health.c +60 -15 modified

Full Patch

diff --git a/android/health.c b/android/health.c
index 8e4ad56..0b86d0f 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1297,24 +1297,18 @@ static struct health_channel *create_channel(struct health_app *app,
 	return channel;
 }
 
-static struct health_channel *connect_channel(struct mcap_mcl *mcl,
-								uint8_t mdepid)
+static struct health_channel *connect_channel(struct health_app *app,
+							struct mcap_mcl *mcl,
+							uint8_t mdepid)
 {
-	struct health_app *app;
 	struct health_device *device;
 	struct health_channel *channel = NULL;
 	bdaddr_t addr;
 
-	DBG("mcl %p mdepid %u", mcl, mdepid);
+	DBG("app %p mdepid %u", app, mdepid);
 
 	mcap_mcl_get_addr(mcl, &addr);
 
-	if (mdepid == MDEP_ECHO)
-		/* For echo service take last app */
-		app = queue_peek_tail(apps);
-	else
-		app = search_app_by_mdepid(mdepid);
-
 	if (!app) {
 		DBG("No app found for mdepid %u", mdepid);
 		return NULL;
@@ -1326,25 +1320,41 @@ static struct health_channel *connect_channel(struct mcap_mcl *mcl,
 
 	channel = create_channel(app, mdepid, device);
 
-	/* Channel is assigned here after creation */
-	mcl->cb->user_data = channel;
-
 	return channel;
 }
 
+static uint8_t conf_to_l2cap(uint8_t conf)
+{
+	return conf == CHANNEL_TYPE_STREAM ? L2CAP_MODE_STREAMING :
+								L2CAP_MODE_ERTM;
+}
+
 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;
+	struct health_app *app;
+	struct mdep_cfg *mdep;
 
 	DBG("Data channel request: mdepid %u mdlid %u", mdepid, mdlid);
 
-	/* TODO: find / create device */
-	channel = connect_channel(mcl, mdepid);
+	if (mdepid == MDEP_ECHO)
+		/* For echo service take last app */
+		app = queue_peek_tail(apps);
+	else
+		app = search_app_by_mdepid(mdepid);
+
+	if (!app)
+		return MCAP_MDL_BUSY;
+
+	channel = connect_channel(app, mcl, mdepid);
 	if (!channel)
 		return MCAP_MDL_BUSY;
 
+	/* Channel is assigned here after creation */
+	mcl->cb->user_data = channel;
+
 	if (mdepid == MDEP_ECHO) {
 		switch (*conf) {
 		case CHANNEL_TYPE_ANY:
@@ -1375,6 +1385,41 @@ static uint8_t mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
 		return MCAP_SUCCESS;
 	}
 
+	mdep = queue_find(app->mdeps, match_mdep_by_id, INT_TO_PTR(mdepid));
+	if (!mdep)
+		return MCAP_MDL_BUSY;
+
+	switch (*conf) {
+	case CHANNEL_TYPE_ANY:
+		if (mdep->role == HAL_HEALTH_MDEP_ROLE_SINK)
+			return MCAP_CONFIGURATION_REJECTED;
+		else
+			*conf = CHANNEL_TYPE_RELIABLE;
+		break;
+	case CHANNEL_TYPE_STREAM:
+		if (mdep->role == HAL_HEALTH_MDEP_ROLE_SOURCE)
+			return MCAP_CONFIGURATION_REJECTED;
+		break;
+	case CHANNEL_TYPE_RELIABLE:
+		if (mdep->role == HAL_HEALTH_MDEP_ROLE_SOURCE)
+			return MCAP_CONFIGURATION_REJECTED;
+		break;
+	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, conf_to_l2cap(*conf), &gerr)) {
+		error("health: error setting L2CAP mode: %s", gerr->message);
+		g_error_free(gerr);
+		return MCAP_MDL_BUSY;
+	}
+
 	return MCAP_SUCCESS;
 }