Home | History | Annotate | Download | only in health
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
      6  *  Authors:
      7  *  Santiago Carot Nemesio <sancane at gmail.com>
      8  *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
      9  *
     10  *  This program is free software; you can redistribute it and/or modify
     11  *  it under the terms of the GNU General Public License as published by
     12  *  the Free Software Foundation; either version 2 of the License, or
     13  *  (at your option) any later version.
     14  *
     15  *  This program is distributed in the hope that it will be useful,
     16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18  *  GNU General Public License for more details.
     19  *
     20  *  You should have received a copy of the GNU General Public License
     21  *  along with this program; if not, write to the Free Software
     22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     23  *
     24  */
     25 
     26 #include <gdbus.h>
     27 
     28 #include "log.h"
     29 #include "error.h"
     30 #include <stdlib.h>
     31 #include <stdint.h>
     32 #include <hdp_types.h>
     33 #include <hdp_util.h>
     34 #include <adapter.h>
     35 #include <device.h>
     36 #include <hdp.h>
     37 #include <mcap.h>
     38 #include <btio.h>
     39 #include <mcap_lib.h>
     40 #include <bluetooth/l2cap.h>
     41 #include <sdpd.h>
     42 #include "../src/dbus-common.h"
     43 #include <unistd.h>
     44 
     45 #ifndef DBUS_TYPE_UNIX_FD
     46 	#define DBUS_TYPE_UNIX_FD -1
     47 #endif
     48 
     49 #define ECHO_TIMEOUT	1 /* second */
     50 #define HDP_ECHO_LEN	15
     51 
     52 static DBusConnection *connection = NULL;
     53 
     54 static GSList *applications = NULL;
     55 static GSList *devices = NULL;
     56 static uint8_t next_app_id = HDP_MDEP_INITIAL;
     57 
     58 static GSList *adapters;
     59 
     60 static gboolean update_adapter(struct hdp_adapter *adapter);
     61 static struct hdp_device *create_health_device(DBusConnection *conn,
     62 						struct btd_device *device);
     63 static void free_echo_data(struct hdp_echo_data *edata);
     64 
     65 struct hdp_create_dc {
     66 	DBusConnection			*conn;
     67 	DBusMessage			*msg;
     68 	struct hdp_application		*app;
     69 	struct hdp_device		*dev;
     70 	uint8_t				config;
     71 	uint8_t				mdep;
     72 	guint				ref;
     73 	mcap_mdl_operation_cb		cb;
     74 };
     75 
     76 struct hdp_tmp_dc_data {
     77 	DBusConnection			*conn;
     78 	DBusMessage			*msg;
     79 	struct hdp_channel		*hdp_chann;
     80 	guint				ref;
     81 	mcap_mdl_operation_cb		cb;
     82 };
     83 
     84 struct hdp_echo_data {
     85 	gboolean		echo_done;	/* Is a echo was already done */
     86 	gpointer		buf;		/* echo packet sent */
     87 	uint			tid;		/* echo timeout */
     88 };
     89 
     90 static struct hdp_channel *hdp_channel_ref(struct hdp_channel *chan)
     91 {
     92 	if (!chan)
     93 		return NULL;
     94 
     95 	chan->ref++;
     96 
     97 	DBG("health_channel_ref(%p): ref=%d", chan, chan->ref);
     98 	return chan;
     99 }
    100 
    101 static void free_health_channel(struct hdp_channel *chan)
    102 {
    103 	if (chan->mdep == HDP_MDEP_ECHO) {
    104 		free_echo_data(chan->edata);
    105 		chan->edata = NULL;
    106 	}
    107 
    108 	mcap_mdl_unref(chan->mdl);
    109 	hdp_application_unref(chan->app);
    110 	health_device_unref(chan->dev);
    111 	g_free(chan->path);
    112 	g_free(chan);
    113 }
    114 
    115 static void hdp_channel_unref(struct hdp_channel *chan)
    116 {
    117 	if (!chan)
    118 		return;
    119 
    120 	chan->ref --;
    121 	DBG("health_channel_unref(%p): ref=%d", chan, chan->ref);
    122 
    123 	if (chan->ref > 0)
    124 		return;
    125 
    126 	free_health_channel(chan);
    127 }
    128 
    129 static void free_hdp_create_dc(struct hdp_create_dc *dc_data)
    130 {
    131 	dbus_message_unref(dc_data->msg);
    132 	dbus_connection_unref(dc_data->conn);
    133 	hdp_application_unref(dc_data->app);
    134 	health_device_unref(dc_data->dev);
    135 
    136 	g_free(dc_data);
    137 }
    138 
    139 static struct hdp_create_dc *hdp_create_data_ref(struct hdp_create_dc *dc_data)
    140 {
    141 	dc_data->ref++;
    142 
    143 	DBG("hdp_create_data_ref(%p): ref=%d", dc_data, dc_data->ref);
    144 
    145 	return dc_data;
    146 }
    147 
    148 static void hdp_create_data_unref(struct hdp_create_dc *dc_data)
    149 {
    150 	dc_data->ref--;
    151 
    152 	DBG("hdp_create_data_unref(%p): ref=%d", dc_data, dc_data->ref);
    153 
    154 	if (dc_data->ref > 0)
    155 		return;
    156 
    157 	free_hdp_create_dc(dc_data);
    158 }
    159 
    160 static void free_hdp_conn_dc(struct hdp_tmp_dc_data *data)
    161 {
    162 	dbus_message_unref(data->msg);
    163 	dbus_connection_unref(data->conn);
    164 	hdp_channel_unref(data->hdp_chann);
    165 
    166 	g_free(data);
    167 }
    168 
    169 static struct hdp_tmp_dc_data *hdp_tmp_dc_data_ref(struct hdp_tmp_dc_data *data)
    170 {
    171 	data->ref++;
    172 
    173 	DBG("hdp_conn_data_ref(%p): ref=%d", data, data->ref);
    174 
    175 	return data;
    176 }
    177 
    178 static void hdp_tmp_dc_data_unref(struct hdp_tmp_dc_data *data)
    179 {
    180 	data->ref--;
    181 
    182 	DBG("hdp_conn_data_unref(%p): ref=%d", data, data->ref);
    183 
    184 	if (data->ref > 0)
    185 		return;
    186 
    187 	free_hdp_conn_dc(data);
    188 }
    189 
    190 static int cmp_app_id(gconstpointer a, gconstpointer b)
    191 {
    192 	const struct hdp_application *app = a;
    193 	const uint8_t *id = b;
    194 
    195 	return app->id - *id;
    196 }
    197 
    198 static int cmp_adapter(gconstpointer a, gconstpointer b)
    199 {
    200 	const struct hdp_adapter *hdp_adapter = a;
    201 	const struct btd_adapter *adapter = b;
    202 
    203 	if (hdp_adapter->btd_adapter == adapter)
    204 		return 0;
    205 
    206 	return -1;
    207 }
    208 
    209 static int cmp_device(gconstpointer a, gconstpointer b)
    210 {
    211 	const struct hdp_device *hdp_device = a;
    212 	const struct btd_device *device = b;
    213 
    214 	if (hdp_device->dev == device)
    215 		return 0;
    216 
    217 	return -1;
    218 }
    219 
    220 static gint cmp_dev_addr(gconstpointer a, gconstpointer dst)
    221 {
    222 	const struct hdp_device *device = a;
    223 	bdaddr_t addr;
    224 
    225 	device_get_address(device->dev, &addr);
    226 	return bacmp(&addr, dst);
    227 }
    228 
    229 static gint cmp_dev_mcl(gconstpointer a, gconstpointer mcl)
    230 {
    231 	const struct hdp_device *device = a;
    232 
    233 	if (mcl == device->mcl)
    234 		return 0;
    235 	return -1;
    236 }
    237 
    238 static gint cmp_chan_mdlid(gconstpointer a, gconstpointer b)
    239 {
    240 	const struct hdp_channel *chan = a;
    241 	const uint16_t *mdlid = b;
    242 
    243 	return chan->mdlid - *mdlid;
    244 }
    245 
    246 static gint cmp_chan_path(gconstpointer a, gconstpointer b)
    247 {
    248 	const struct hdp_channel *chan = a;
    249 	const char *path = b;
    250 
    251 	return g_ascii_strcasecmp(chan->path, path);
    252 }
    253 
    254 static gint cmp_chan_mdl(gconstpointer a, gconstpointer mdl)
    255 {
    256 	const struct hdp_channel *chan = a;
    257 
    258 	if (chan->mdl == mdl)
    259 		return 0;
    260 	return -1;
    261 }
    262 
    263 static uint8_t get_app_id(void)
    264 {
    265 	uint8_t id = next_app_id;
    266 
    267 	do {
    268 		GSList *l = g_slist_find_custom(applications, &id, cmp_app_id);
    269 
    270 		if (!l) {
    271 			next_app_id = (id % HDP_MDEP_FINAL) + 1;
    272 			return id;
    273 		} else
    274 			id = (id % HDP_MDEP_FINAL) + 1;
    275 	} while (id != next_app_id);
    276 
    277 	/* No more ids available */
    278 	return 0;
    279 }
    280 
    281 static int cmp_app(gconstpointer a, gconstpointer b)
    282 {
    283 	const struct hdp_application *app = a;
    284 
    285 	return g_strcmp0(app->path, b);
    286 }
    287 
    288 static gboolean set_app_path(struct hdp_application *app)
    289 {
    290 	app->id = get_app_id();
    291 	if (!app->id)
    292 		return FALSE;
    293 	app->path = g_strdup_printf(MANAGER_PATH "/health_app_%d", app->id);
    294 
    295 	return TRUE;
    296 };
    297 
    298 static void device_unref_mcl(struct hdp_device *hdp_device)
    299 {
    300 	if (!hdp_device->mcl)
    301 		return;
    302 
    303 	mcap_close_mcl(hdp_device->mcl, FALSE);
    304 	mcap_mcl_unref(hdp_device->mcl);
    305 	hdp_device->mcl = NULL;
    306 	hdp_device->mcl_conn = FALSE;
    307 }
    308 
    309 static void free_health_device(struct hdp_device *device)
    310 {
    311 	if (device->conn) {
    312 		dbus_connection_unref(device->conn);
    313 		device->conn = NULL;
    314 	}
    315 
    316 	if (device->dev) {
    317 		btd_device_unref(device->dev);
    318 		device->dev = NULL;
    319 	}
    320 
    321 	device_unref_mcl(device);
    322 
    323 	g_free(device);
    324 }
    325 
    326 static void remove_application(struct hdp_application *app)
    327 {
    328 	DBG("Application %s deleted", app->path);
    329 	hdp_application_unref(app);
    330 
    331 	g_slist_foreach(adapters, (GFunc) update_adapter, NULL);
    332 }
    333 
    334 static void client_disconnected(DBusConnection *conn, void *user_data)
    335 {
    336 	struct hdp_application *app = user_data;
    337 
    338 	DBG("Client disconnected from the bus, deleting hdp application");
    339 	applications = g_slist_remove(applications, app);
    340 
    341 	app->dbus_watcher = 0; /* Watcher shouldn't be freed in this case */
    342 	remove_application(app);
    343 }
    344 
    345 static DBusMessage *manager_create_application(DBusConnection *conn,
    346 					DBusMessage *msg, void *user_data)
    347 {
    348 	struct hdp_application *app;
    349 	const char *name;
    350 	DBusMessageIter iter;
    351 	GError *err = NULL;
    352 
    353 	dbus_message_iter_init(msg, &iter);
    354 	app = hdp_get_app_config(&iter, &err);
    355 	if (err) {
    356 		g_error_free(err);
    357 		return btd_error_invalid_args(msg);
    358 	}
    359 
    360 	name = dbus_message_get_sender(msg);
    361 	if (!name) {
    362 		hdp_application_unref(app);
    363 		return g_dbus_create_error(msg,
    364 					ERROR_INTERFACE ".HealthError",
    365 					"Can't get sender name");
    366 	}
    367 
    368 	if (!set_app_path(app)) {
    369 		hdp_application_unref(app);
    370 		return g_dbus_create_error(msg,
    371 				ERROR_INTERFACE ".HealthError",
    372 				"Can't get a valid id for the application");
    373 	}
    374 
    375 	app->oname = g_strdup(name);
    376 	app->conn = dbus_connection_ref(conn);
    377 
    378 	applications = g_slist_prepend(applications, app);
    379 
    380 	app->dbus_watcher = g_dbus_add_disconnect_watch(conn, name,
    381 						client_disconnected, app, NULL);
    382 	g_slist_foreach(adapters, (GFunc) update_adapter, NULL);
    383 
    384 	DBG("Health application created with id %s", app->path);
    385 
    386 	return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &app->path,
    387 							DBUS_TYPE_INVALID);
    388 }
    389 
    390 static DBusMessage *manager_destroy_application(DBusConnection *conn,
    391 					DBusMessage *msg, void *user_data)
    392 {
    393 	const char *path;
    394 	struct hdp_application *app;
    395 	GSList *l;
    396 
    397 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
    398 						DBUS_TYPE_INVALID))
    399 		return btd_error_invalid_args(msg);
    400 
    401 	l = g_slist_find_custom(applications, path, cmp_app);
    402 
    403 	if (!l)
    404 		return g_dbus_create_error(msg,
    405 					ERROR_INTERFACE ".InvalidArguments",
    406 					"Invalid arguments in method call, "
    407 					"no such application");
    408 
    409 	app = l->data;
    410 	applications = g_slist_remove(applications, app);
    411 
    412 	remove_application(app);
    413 
    414 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
    415 }
    416 
    417 static void manager_path_unregister(gpointer data)
    418 {
    419 	g_slist_foreach(applications, (GFunc) hdp_application_unref, NULL);
    420 
    421 	g_slist_free(applications);
    422 	applications = NULL;
    423 
    424 	g_slist_foreach(adapters, (GFunc) update_adapter, NULL);
    425 }
    426 
    427 static GDBusMethodTable health_manager_methods[] = {
    428 	{"CreateApplication", "a{sv}", "o", manager_create_application},
    429 	{"DestroyApplication", "o", "", manager_destroy_application},
    430 	{ NULL }
    431 };
    432 
    433 static DBusMessage *channel_get_properties(DBusConnection *conn,
    434 					DBusMessage *msg, void *user_data)
    435 {
    436 	struct hdp_channel *chan = user_data;
    437 	DBusMessageIter iter, dict;
    438 	DBusMessage *reply;
    439 	const char *path;
    440 	char *type;
    441 
    442 	reply = dbus_message_new_method_return(msg);
    443 	if (!reply)
    444 		return NULL;
    445 
    446 	dbus_message_iter_init_append(reply, &iter);
    447 
    448 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    449 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    450 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    451 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    452 
    453 	path = device_get_path(chan->dev->dev);
    454 	dict_append_entry(&dict, "Device", DBUS_TYPE_OBJECT_PATH, &path);
    455 
    456 	path = chan->app->path;
    457 	dict_append_entry(&dict, "Application", DBUS_TYPE_OBJECT_PATH, &path);
    458 
    459 	if (chan->config == HDP_RELIABLE_DC)
    460 		type = g_strdup("Reliable");
    461 	else
    462 		type = g_strdup("Streaming");
    463 
    464 	dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &type);
    465 
    466 	g_free(type);
    467 
    468 	dbus_message_iter_close_container(&iter, &dict);
    469 
    470 	return reply;
    471 }
    472 
    473 static void hdp_tmp_dc_data_destroy(gpointer data)
    474 {
    475 	struct hdp_tmp_dc_data *hdp_conn = data;
    476 
    477 	hdp_tmp_dc_data_unref(hdp_conn);
    478 }
    479 
    480 static void abort_mdl_cb(GError *err, gpointer data)
    481 {
    482 	struct hdp_device *dev;
    483 	struct hdp_channel *hdp_chan = data;
    484 	if (err)
    485 		error("Aborting error: %s", err->message);
    486 
    487 	if (hdp_chan) {
    488 		dev = hdp_chan->dev;
    489 		if (dev && hdp_chan->mdep != HDP_MDEP_ECHO)
    490 			g_dbus_emit_signal(dev->conn,
    491 						device_get_path(dev->dev),
    492 						HEALTH_DEVICE,
    493 						"ChannelConnected",
    494 						DBUS_TYPE_OBJECT_PATH,
    495 						&hdp_chan->path,
    496 						DBUS_TYPE_INVALID);
    497 	}
    498 }
    499 
    500 static void hdp_mdl_reconn_cb(struct mcap_mdl *mdl, GError *err, gpointer data)
    501 {
    502 	struct hdp_tmp_dc_data *dc_data = data;
    503 	DBusMessage *reply;
    504 	int fd;
    505 
    506 	if (err) {
    507 		struct hdp_channel *chan = dc_data->hdp_chann;
    508 		GError *gerr = NULL;
    509 
    510 		error("%s", err->message);
    511 		reply = g_dbus_create_error(dc_data->msg,
    512 					ERROR_INTERFACE ".HealthError",
    513 					"Cannot reconnect: %s", err->message);
    514 		g_dbus_send_message(dc_data->conn, reply);
    515 
    516 		/* Send abort request because remote side */
    517 		/* is now in PENDING state */
    518 		if (!mcap_mdl_abort(chan->mdl, abort_mdl_cb, NULL, NULL,
    519 								&gerr)) {
    520 			error("%s", gerr->message);
    521 			g_error_free(gerr);
    522 		}
    523 		return;
    524 	}
    525 
    526 	fd = mcap_mdl_get_fd(dc_data->hdp_chann->mdl);
    527 	if (fd < 0) {
    528 		reply = g_dbus_create_error(dc_data->msg,
    529 						ERROR_INTERFACE ".HealthError",
    530 						"Cannot get file descriptor");
    531 		g_dbus_send_message(dc_data->conn, reply);
    532 		return;
    533 	}
    534 
    535 	reply = g_dbus_create_reply(dc_data->msg, DBUS_TYPE_UNIX_FD,
    536 							&fd, DBUS_TYPE_INVALID);
    537 	g_dbus_send_message(dc_data->conn, reply);
    538 
    539 	g_dbus_emit_signal(dc_data->conn,
    540 			device_get_path(dc_data->hdp_chann->dev->dev),
    541 			HEALTH_DEVICE, "ChannelConnected",
    542 			DBUS_TYPE_OBJECT_PATH, &dc_data->hdp_chann->path,
    543 			DBUS_TYPE_INVALID);
    544 }
    545 
    546 static void hdp_get_dcpsm_cb(uint16_t dcpsm, gpointer user_data, GError *err)
    547 {
    548 	struct hdp_tmp_dc_data *hdp_conn = user_data;
    549 	struct hdp_channel *hdp_chann = hdp_conn->hdp_chann;
    550 	GError *gerr = NULL;
    551 	uint8_t mode;
    552 
    553 	if (err) {
    554 		hdp_conn->cb(hdp_chann->mdl, err, hdp_conn);
    555 		return;
    556 	}
    557 
    558 	if (hdp_chann->config == HDP_RELIABLE_DC)
    559 		mode = L2CAP_MODE_ERTM;
    560 	else
    561 		mode = L2CAP_MODE_STREAMING;
    562 
    563 	if (mcap_connect_mdl(hdp_chann->mdl, mode, dcpsm, hdp_conn->cb,
    564 					hdp_tmp_dc_data_ref(hdp_conn),
    565 					hdp_tmp_dc_data_destroy, &gerr))
    566 		return;
    567 
    568 	hdp_tmp_dc_data_unref(hdp_conn);
    569 	hdp_conn->cb(hdp_chann->mdl, err, hdp_conn);
    570 	g_error_free(gerr);
    571 	gerr = NULL;
    572 }
    573 
    574 static void device_reconnect_mdl_cb(struct mcap_mdl *mdl, GError *err,
    575 								gpointer data)
    576 {
    577 	struct hdp_tmp_dc_data *dc_data = data;
    578 	GError *gerr = NULL;
    579 	DBusMessage *reply;
    580 
    581 	if (err) {
    582 		reply = g_dbus_create_error(dc_data->msg,
    583 					ERROR_INTERFACE ".HealthError",
    584 					"Cannot reconnect: %s", err->message);
    585 		g_dbus_send_message(dc_data->conn, reply);
    586 		return;
    587 	}
    588 
    589 	dc_data->cb = hdp_mdl_reconn_cb;
    590 
    591 	if (hdp_get_dcpsm(dc_data->hdp_chann->dev, hdp_get_dcpsm_cb,
    592 					hdp_tmp_dc_data_ref(dc_data),
    593 					hdp_tmp_dc_data_destroy, &gerr))
    594 		return;
    595 
    596 	error("%s", gerr->message);
    597 
    598 	reply = g_dbus_create_error(dc_data->msg,
    599 					ERROR_INTERFACE ".HealthError",
    600 					"Cannot reconnect: %s", gerr->message);
    601 	g_dbus_send_message(dc_data->conn, reply);
    602 	hdp_tmp_dc_data_unref(dc_data);
    603 	g_error_free(gerr);
    604 
    605 	/* Send abort request because remote side is now in PENDING state */
    606 	if (!mcap_mdl_abort(mdl, abort_mdl_cb, NULL, NULL, &gerr)) {
    607 		error("%s", gerr->message);
    608 		g_error_free(gerr);
    609 	}
    610 }
    611 
    612 static DBusMessage *channel_acquire_continue(struct hdp_tmp_dc_data *data,
    613 								GError *err)
    614 {
    615 	DBusMessage *reply;
    616 	GError *gerr = NULL;
    617 	int fd;
    618 
    619 	if (err) {
    620 		return g_dbus_create_error(data->msg,
    621 						ERROR_INTERFACE ".HealthError",
    622 						"%s", err->message);
    623 	}
    624 
    625 	fd = mcap_mdl_get_fd(data->hdp_chann->mdl);
    626 	if (fd >= 0)
    627 		return g_dbus_create_reply(data->msg, DBUS_TYPE_UNIX_FD, &fd,
    628 							DBUS_TYPE_INVALID);
    629 
    630 	hdp_tmp_dc_data_ref(data);
    631 	if (mcap_reconnect_mdl(data->hdp_chann->mdl, device_reconnect_mdl_cb,
    632 					data, hdp_tmp_dc_data_destroy, &gerr))
    633 		return NULL;
    634 
    635 	hdp_tmp_dc_data_unref(data);
    636 	reply = g_dbus_create_error(data->msg, ERROR_INTERFACE ".HealthError",
    637 					"Cannot reconnect: %s", gerr->message);
    638 	g_error_free(gerr);
    639 
    640 	return reply;
    641 }
    642 
    643 static void channel_acquire_cb(gpointer data, GError *err)
    644 {
    645 	struct hdp_tmp_dc_data *dc_data = data;
    646 	DBusMessage *reply;
    647 
    648 	reply = channel_acquire_continue(data, err);
    649 
    650 	if (reply)
    651 		g_dbus_send_message(dc_data->conn, reply);
    652 }
    653 
    654 static DBusMessage *channel_acquire(DBusConnection *conn,
    655 					DBusMessage *msg, void *user_data)
    656 {
    657 	struct hdp_channel *chan = user_data;
    658 	struct hdp_tmp_dc_data *dc_data;
    659 	GError *gerr = NULL;
    660 	DBusMessage *reply;
    661 
    662 	dc_data = g_new0(struct hdp_tmp_dc_data, 1);
    663 	dc_data->conn = dbus_connection_ref(conn);
    664 	dc_data->msg = dbus_message_ref(msg);
    665 	dc_data->hdp_chann = hdp_channel_ref(chan);
    666 
    667 	if (chan->dev->mcl_conn) {
    668 		reply = channel_acquire_continue(hdp_tmp_dc_data_ref(dc_data),
    669 									NULL);
    670 		hdp_tmp_dc_data_unref(dc_data);
    671 		return reply;
    672 	}
    673 
    674 	if (hdp_establish_mcl(chan->dev, channel_acquire_cb,
    675 						hdp_tmp_dc_data_ref(dc_data),
    676 						hdp_tmp_dc_data_destroy, &gerr))
    677 		return NULL;
    678 
    679 	reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
    680 					"%s", gerr->message);
    681 	hdp_tmp_dc_data_unref(dc_data);
    682 	g_error_free(gerr);
    683 
    684 	return reply;
    685 }
    686 
    687 static void close_mdl(struct hdp_channel *hdp_chann)
    688 {
    689 	int fd;
    690 
    691 	fd = mcap_mdl_get_fd(hdp_chann->mdl);
    692 	if (fd < 0)
    693 		return;
    694 
    695 	close(fd);
    696 }
    697 
    698 static DBusMessage *channel_release(DBusConnection *conn,
    699 					DBusMessage *msg, void *user_data)
    700 {
    701 	struct hdp_channel *hdp_chann = user_data;
    702 
    703 	close_mdl(hdp_chann);
    704 
    705 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
    706 }
    707 
    708 static void free_echo_data(struct hdp_echo_data *edata)
    709 {
    710 	if (!edata)
    711 		return;
    712 
    713 	if (edata->tid)
    714 		g_source_remove(edata->tid);
    715 
    716 	if (edata->buf)
    717 		g_free(edata->buf);
    718 
    719 
    720 	g_free(edata);
    721 }
    722 
    723 static void health_channel_destroy(void *data)
    724 {
    725 	struct hdp_channel *hdp_chan = data;
    726 	struct hdp_device *dev = hdp_chan->dev;
    727 
    728 	DBG("Destroy Health Channel %s", hdp_chan->path);
    729 	if (!g_slist_find(dev->channels, hdp_chan))
    730 		goto end;
    731 
    732 	dev->channels = g_slist_remove(dev->channels, hdp_chan);
    733 
    734 	if (hdp_chan->mdep != HDP_MDEP_ECHO)
    735 		g_dbus_emit_signal(dev->conn, device_get_path(dev->dev),
    736 					HEALTH_DEVICE, "ChannelDeleted",
    737 					DBUS_TYPE_OBJECT_PATH, &hdp_chan->path,
    738 					DBUS_TYPE_INVALID);
    739 
    740 	if (hdp_chan == dev->fr) {
    741 		char *empty_path;
    742 
    743 		hdp_channel_unref(dev->fr);
    744 		dev->fr = NULL;
    745 		empty_path = "/";
    746 		emit_property_changed(dev->conn, device_get_path(dev->dev),
    747 					HEALTH_DEVICE, "MainChannel",
    748 					DBUS_TYPE_OBJECT_PATH, &empty_path);
    749 	}
    750 
    751 end:
    752 	hdp_channel_unref(hdp_chan);
    753 }
    754 
    755 static GDBusMethodTable health_channels_methods[] = {
    756 	{"GetProperties","",	"a{sv}",	channel_get_properties },
    757 	{"Acquire",	"",	"h",		channel_acquire,
    758 						G_DBUS_METHOD_FLAG_ASYNC },
    759 	{"Release",	"",	"",		channel_release },
    760 	{ NULL }
    761 };
    762 
    763 static struct hdp_channel *create_channel(struct hdp_device *dev,
    764 						uint8_t config,
    765 						struct mcap_mdl *mdl,
    766 						uint16_t mdlid,
    767 						struct hdp_application *app,
    768 						GError **err)
    769 {
    770 	struct hdp_channel *hdp_chann;
    771 
    772 	if (!dev)
    773 		return NULL;
    774 
    775 	hdp_chann = g_new0(struct hdp_channel, 1);
    776 	hdp_chann->config = config;
    777 	hdp_chann->dev = health_device_ref(dev);
    778 	hdp_chann->mdlid = mdlid;
    779 
    780 	if (mdl)
    781 		hdp_chann->mdl = mcap_mdl_ref(mdl);
    782 
    783 	if (app) {
    784 		hdp_chann->mdep = app->id;
    785 		hdp_chann->app = hdp_application_ref(app);
    786 	} else
    787 		hdp_chann->edata = g_new0(struct hdp_echo_data, 1);
    788 
    789 	hdp_chann->path = g_strdup_printf("%s/chan%d",
    790 					device_get_path(hdp_chann->dev->dev),
    791 					hdp_chann->mdlid);
    792 
    793 	dev->channels = g_slist_append(dev->channels,
    794 						hdp_channel_ref(hdp_chann));
    795 
    796 	if (hdp_chann->mdep == HDP_MDEP_ECHO)
    797 		return hdp_channel_ref(hdp_chann);
    798 
    799 	if (!g_dbus_register_interface(dev->conn, hdp_chann->path,
    800 					HEALTH_CHANNEL,
    801 					health_channels_methods, NULL, NULL,
    802 					hdp_chann, health_channel_destroy)) {
    803 		g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
    804 					"Can't register the channel interface");
    805 		health_channel_destroy(hdp_chann);
    806 		return NULL;
    807 	}
    808 
    809 	return hdp_channel_ref(hdp_chann);
    810 }
    811 
    812 static void remove_channels(struct hdp_device *dev)
    813 {
    814 	struct hdp_channel *chan;
    815 	char *path;
    816 
    817 	while (dev->channels) {
    818 		chan = dev->channels->data;
    819 
    820 		path = g_strdup(chan->path);
    821 		if (!g_dbus_unregister_interface(dev->conn, path,
    822 								HEALTH_CHANNEL))
    823 			health_channel_destroy(chan);
    824 		g_free(path);
    825 	}
    826 }
    827 
    828 static void close_device_con(struct hdp_device *dev, gboolean cache)
    829 {
    830 	if (!dev->mcl)
    831 		return;
    832 
    833 	mcap_close_mcl(dev->mcl, cache);
    834 	dev->mcl_conn = FALSE;
    835 
    836 	if (cache)
    837 		return;
    838 
    839 	device_unref_mcl(dev);
    840 	remove_channels(dev);
    841 
    842 	if (!dev->sdp_present) {
    843 		const char *path;
    844 
    845 		path = device_get_path(dev->dev);
    846 		g_dbus_unregister_interface(dev->conn, path, HEALTH_DEVICE);
    847 	}
    848 }
    849 
    850 static int send_echo_data(int sock, const void *buf, uint32_t size)
    851 {
    852 	const uint8_t *buf_b = buf;
    853 	uint32_t sent = 0;
    854 
    855 	while (sent < size) {
    856 		int n = write(sock, buf_b + sent, size - sent);
    857 		if (n < 0)
    858 			return -1;
    859 		sent += n;
    860 	}
    861 
    862 	return 0;
    863 }
    864 
    865 static gboolean serve_echo(GIOChannel *io_chan, GIOCondition cond,
    866 								gpointer data)
    867 {
    868 	struct hdp_channel *chan = data;
    869 	uint8_t buf[MCAP_DC_MTU];
    870 	int fd, len;
    871 
    872 	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
    873 		hdp_channel_unref(chan);
    874 		return FALSE;
    875 	}
    876 
    877 	if (chan->edata->echo_done)
    878 		goto fail;
    879 
    880 	chan->edata->echo_done = TRUE;
    881 
    882 	fd = g_io_channel_unix_get_fd(io_chan);
    883 	len = read(fd, buf, sizeof(buf));
    884 
    885 	if (send_echo_data(fd, buf, len)  >= 0)
    886 		return TRUE;
    887 
    888 fail:
    889 	close_device_con(chan->dev, FALSE);
    890 	hdp_channel_unref(chan);
    891 	return FALSE;
    892 }
    893 
    894 static gboolean check_channel_conf(struct hdp_channel *chan)
    895 {
    896 	GError *err = NULL;
    897 	GIOChannel *io;
    898 	uint8_t mode;
    899 	uint16_t imtu, omtu;
    900 	int fd;
    901 
    902 	fd = mcap_mdl_get_fd(chan->mdl);
    903 	if (fd < 0)
    904 		return FALSE;
    905 	io = g_io_channel_unix_new(fd);
    906 
    907 	if (!bt_io_get(io, BT_IO_L2CAP, &err,
    908 			BT_IO_OPT_MODE, &mode,
    909 			BT_IO_OPT_IMTU, &imtu,
    910 			BT_IO_OPT_OMTU, &omtu,
    911 			BT_IO_OPT_INVALID)) {
    912 		error("Error: %s", err->message);
    913 		g_io_channel_unref(io);
    914 		g_error_free(err);
    915 		return FALSE;
    916 	}
    917 
    918 	g_io_channel_unref(io);
    919 
    920 	switch (chan->config) {
    921 	case HDP_RELIABLE_DC:
    922 		if (mode != L2CAP_MODE_ERTM)
    923 			return FALSE;
    924 		break;
    925 	case HDP_STREAMING_DC:
    926 		if (mode != L2CAP_MODE_STREAMING)
    927 			return FALSE;
    928 		break;
    929 	default:
    930 		error("Error: Connected with unknown configuration");
    931 		return FALSE;
    932 	}
    933 
    934 	DBG("MDL imtu %d omtu %d Channel imtu %d omtu %d", imtu, omtu,
    935 						chan->imtu, chan->omtu);
    936 
    937 	if (!chan->imtu)
    938 		chan->imtu = imtu;
    939 	if (!chan->omtu)
    940 		chan->omtu = omtu;
    941 
    942 	if (chan->imtu != imtu || chan->omtu != omtu)
    943 		return FALSE;
    944 
    945 	return TRUE;
    946 }
    947 
    948 static void hdp_mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data)
    949 {
    950 	struct hdp_device *dev = data;
    951 	struct hdp_channel *chan;
    952 
    953 	DBG("hdp_mcap_mdl_connected_cb");
    954 	if (!dev->ndc)
    955 		return;
    956 
    957 	chan = dev->ndc;
    958 	if (!chan->mdl)
    959 		chan->mdl = mcap_mdl_ref(mdl);
    960 
    961 	if (!g_slist_find(dev->channels, chan))
    962 		dev->channels = g_slist_prepend(dev->channels,
    963 							hdp_channel_ref(chan));
    964 
    965 	if (!check_channel_conf(chan)) {
    966 		close_mdl(chan);
    967 		goto end;
    968 	}
    969 
    970 	if (chan->mdep == HDP_MDEP_ECHO) {
    971 		GIOChannel *io;
    972 		int fd;
    973 
    974 		fd = mcap_mdl_get_fd(chan->mdl);
    975 		if (fd < 0)
    976 			goto end;
    977 
    978 		chan->edata->echo_done = FALSE;
    979 		io = g_io_channel_unix_new(fd);
    980 		g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN,
    981 				serve_echo, hdp_channel_ref(chan));
    982 		g_io_channel_unref(io);
    983 		goto end;
    984 	}
    985 
    986 	g_dbus_emit_signal(dev->conn, device_get_path(dev->dev), HEALTH_DEVICE,
    987 					"ChannelConnected",
    988 					DBUS_TYPE_OBJECT_PATH, &chan->path,
    989 					DBUS_TYPE_INVALID);
    990 
    991 	if (dev->fr)
    992 		goto end;
    993 
    994 	dev->fr = hdp_channel_ref(chan);
    995 
    996 	emit_property_changed(dev->conn, device_get_path(dev->dev),
    997 					HEALTH_DEVICE, "MainChannel",
    998 					DBUS_TYPE_OBJECT_PATH, &dev->fr->path);
    999 
   1000 end:
   1001 	hdp_channel_unref(dev->ndc);
   1002 	dev->ndc = NULL;
   1003 }
   1004 
   1005 static void hdp_mcap_mdl_closed_cb(struct mcap_mdl *mdl, void *data)
   1006 {
   1007 	/* struct hdp_device *dev = data; */
   1008 
   1009 	DBG("hdp_mcap_mdl_closed_cb");
   1010 
   1011 	/* Nothing to do */
   1012 }
   1013 
   1014 static void hdp_mcap_mdl_deleted_cb(struct mcap_mdl *mdl, void *data)
   1015 {
   1016 	struct hdp_device *dev = data;
   1017 	struct hdp_channel *chan;
   1018 	char *path;
   1019 	GSList *l;
   1020 
   1021 	DBG("hdp_mcap_mdl_deleted_cb");
   1022 	l = g_slist_find_custom(dev->channels, mdl, cmp_chan_mdl);
   1023 	if (!l)
   1024 		return;
   1025 
   1026 	chan = l->data;
   1027 
   1028 	path = g_strdup(chan->path);
   1029 	if (!g_dbus_unregister_interface(dev->conn, path, HEALTH_CHANNEL))
   1030 		health_channel_destroy(chan);
   1031 	g_free(path);
   1032 }
   1033 
   1034 static void hdp_mcap_mdl_aborted_cb(struct mcap_mdl *mdl, void *data)
   1035 {
   1036 	struct hdp_device *dev = data;
   1037 
   1038 	DBG("hdp_mcap_mdl_aborted_cb");
   1039 	if (!dev->ndc)
   1040 		return;
   1041 
   1042 	dev->ndc->mdl = mcap_mdl_ref(mdl);
   1043 
   1044 	if (!g_slist_find(dev->channels, dev->ndc))
   1045 		dev->channels = g_slist_prepend(dev->channels,
   1046 						hdp_channel_ref(dev->ndc));
   1047 
   1048 	if (dev->ndc->mdep != HDP_MDEP_ECHO)
   1049 		g_dbus_emit_signal(dev->conn, device_get_path(dev->dev),
   1050 					HEALTH_DEVICE, "ChannelConnected",
   1051 					DBUS_TYPE_OBJECT_PATH, &dev->ndc->path,
   1052 					DBUS_TYPE_INVALID);
   1053 
   1054 	hdp_channel_unref(dev->ndc);
   1055 	dev->ndc = NULL;
   1056 }
   1057 
   1058 static uint8_t hdp2l2cap_mode(uint8_t hdp_mode)
   1059 {
   1060 	return hdp_mode == HDP_STREAMING_DC ? L2CAP_MODE_STREAMING :
   1061 								L2CAP_MODE_ERTM;
   1062 }
   1063 
   1064 static uint8_t hdp_mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
   1065 				uint16_t mdlid, uint8_t *conf, void *data)
   1066 {
   1067 	struct hdp_device *dev = data;
   1068 	struct hdp_application *app;
   1069 	GError *err = NULL;
   1070 	GSList *l;
   1071 
   1072 	DBG("Data channel request");
   1073 
   1074 	if (mdepid == HDP_MDEP_ECHO) {
   1075 		switch (*conf) {
   1076 		case HDP_NO_PREFERENCE_DC:
   1077 			*conf = HDP_RELIABLE_DC;
   1078 		case HDP_RELIABLE_DC:
   1079 			break;
   1080 		case HDP_STREAMING_DC:
   1081 			return MCAP_CONFIGURATION_REJECTED;
   1082 		default:
   1083 			/* Special case defined in HDP spec 3.4. When an invalid
   1084 			* configuration is received we shall close the MCL when
   1085 			* we are still processing the callback. */
   1086 			close_device_con(dev, FALSE);
   1087 			return MCAP_CONFIGURATION_REJECTED; /* not processed */
   1088 		}
   1089 
   1090 		if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
   1091 						L2CAP_MODE_ERTM, &err)) {
   1092 			error("Error: %s", err->message);
   1093 			g_error_free(err);
   1094 			return MCAP_MDL_BUSY;
   1095 		}
   1096 
   1097 		dev->ndc = create_channel(dev, *conf, NULL, mdlid, NULL, NULL);
   1098 		if (!dev->ndc)
   1099 			return MCAP_MDL_BUSY;
   1100 
   1101 		return MCAP_SUCCESS;
   1102 	}
   1103 
   1104 	l = g_slist_find_custom(applications, &mdepid, cmp_app_id);
   1105 	if (!l)
   1106 		return MCAP_INVALID_MDEP;
   1107 
   1108 	app = l->data;
   1109 
   1110 	/* Check if is the first dc if so,
   1111 	* only reliable configuration is allowed */
   1112 	switch (*conf) {
   1113 	case HDP_NO_PREFERENCE_DC:
   1114 		if (app->role == HDP_SINK)
   1115 			return MCAP_CONFIGURATION_REJECTED;
   1116 		else if (dev->fr && app->chan_type_set)
   1117 			*conf = app->chan_type;
   1118 		else
   1119 			*conf = HDP_RELIABLE_DC;
   1120 		break;
   1121 	case HDP_STREAMING_DC:
   1122 		if (!dev->fr || app->role == HDP_SOURCE)
   1123 			return MCAP_CONFIGURATION_REJECTED;
   1124 	case HDP_RELIABLE_DC:
   1125 		if (app->role == HDP_SOURCE)
   1126 			return MCAP_CONFIGURATION_REJECTED;
   1127 		break;
   1128 	default:
   1129 		/* Special case defined in HDP spec 3.4. When an invalid
   1130 		* configuration is received we shall close the MCL when
   1131 		* we are still processing the callback. */
   1132 		close_device_con(dev, FALSE);
   1133 		return MCAP_CONFIGURATION_REJECTED; /* not processed */
   1134 	}
   1135 
   1136 	l = g_slist_find_custom(dev->channels, &mdlid, cmp_chan_mdlid);
   1137 	if (l) {
   1138 		struct hdp_channel *chan = l->data;
   1139 		char *path;
   1140 
   1141 		path = g_strdup(chan->path);
   1142 		g_dbus_unregister_interface(dev->conn, path, HEALTH_CHANNEL);
   1143 		g_free(path);
   1144 	}
   1145 
   1146 	if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
   1147 						hdp2l2cap_mode(*conf), &err)) {
   1148 		error("Error: %s", err->message);
   1149 		g_error_free(err);
   1150 		return MCAP_MDL_BUSY;
   1151 	}
   1152 
   1153 	dev->ndc = create_channel(dev, *conf, NULL, mdlid, app, NULL);
   1154 	if (!dev->ndc)
   1155 		return MCAP_MDL_BUSY;
   1156 
   1157 	return MCAP_SUCCESS;
   1158 }
   1159 
   1160 static uint8_t hdp_mcap_mdl_reconn_req_cb(struct mcap_mdl *mdl, void *data)
   1161 {
   1162 	struct hdp_device *dev = data;
   1163 	struct hdp_channel *chan;
   1164 	GError *err = NULL;
   1165 	GSList *l;
   1166 
   1167 	l = g_slist_find_custom(dev->channels, mdl, cmp_chan_mdl);
   1168 	if (!l)
   1169 		return MCAP_INVALID_MDL;
   1170 
   1171 	chan = l->data;
   1172 
   1173 	if (!dev->fr && (chan->config != HDP_RELIABLE_DC) &&
   1174 						(chan->mdep != HDP_MDEP_ECHO))
   1175 		return MCAP_UNSPECIFIED_ERROR;
   1176 
   1177 	if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
   1178 					hdp2l2cap_mode(chan->config), &err)) {
   1179 		error("Error: %s", err->message);
   1180 		g_error_free(err);
   1181 		return MCAP_MDL_BUSY;
   1182 	}
   1183 
   1184 	dev->ndc = hdp_channel_ref(chan);
   1185 
   1186 	return MCAP_SUCCESS;
   1187 }
   1188 
   1189 gboolean hdp_set_mcl_cb(struct hdp_device *device, GError **err)
   1190 {
   1191 	gboolean ret;
   1192 
   1193 	if (!device->mcl)
   1194 		return FALSE;
   1195 
   1196 	ret = mcap_mcl_set_cb(device->mcl, device, err,
   1197 		MCAP_MDL_CB_CONNECTED, hdp_mcap_mdl_connected_cb,
   1198 		MCAP_MDL_CB_CLOSED, hdp_mcap_mdl_closed_cb,
   1199 		MCAP_MDL_CB_DELETED, hdp_mcap_mdl_deleted_cb,
   1200 		MCAP_MDL_CB_ABORTED, hdp_mcap_mdl_aborted_cb,
   1201 		MCAP_MDL_CB_REMOTE_CONN_REQ, hdp_mcap_mdl_conn_req_cb,
   1202 		MCAP_MDL_CB_REMOTE_RECONN_REQ, hdp_mcap_mdl_reconn_req_cb,
   1203 		MCAP_MDL_CB_INVALID);
   1204 
   1205 	if (ret)
   1206 		return TRUE;
   1207 
   1208 	error("Can't set mcl callbacks, closing mcl");
   1209 	close_device_con(device, TRUE);
   1210 
   1211 	return FALSE;
   1212 }
   1213 
   1214 static void mcl_connected(struct mcap_mcl *mcl, gpointer data)
   1215 {
   1216 	struct hdp_device *hdp_device;
   1217 	bdaddr_t addr;
   1218 	GSList *l;
   1219 
   1220 	mcap_mcl_get_addr(mcl, &addr);
   1221 	l = g_slist_find_custom(devices, &addr, cmp_dev_addr);
   1222 	if (!l) {
   1223 		struct hdp_adapter *hdp_adapter = data;
   1224 		struct btd_device *device;
   1225 		char str[18];
   1226 
   1227 		ba2str(&addr, str);
   1228 		device = adapter_get_device(connection,
   1229 					hdp_adapter->btd_adapter, str);
   1230 		if (!device)
   1231 			return;
   1232 		hdp_device = create_health_device(connection, device);
   1233 		if (!hdp_device)
   1234 			return;
   1235 		devices = g_slist_append(devices, hdp_device);
   1236 	} else
   1237 		hdp_device = l->data;
   1238 
   1239 	hdp_device->mcl = mcap_mcl_ref(mcl);
   1240 	hdp_device->mcl_conn = TRUE;
   1241 
   1242 	DBG("New mcl connected from  %s", device_get_path(hdp_device->dev));
   1243 
   1244 	hdp_set_mcl_cb(hdp_device, NULL);
   1245 }
   1246 
   1247 static void mcl_reconnected(struct mcap_mcl *mcl, gpointer data)
   1248 {
   1249 	struct hdp_device *hdp_device;
   1250 	GSList *l;
   1251 
   1252 	l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
   1253 	if (!l)
   1254 		return;
   1255 
   1256 	hdp_device = l->data;
   1257 	hdp_device->mcl_conn = TRUE;
   1258 
   1259 	DBG("MCL reconnected %s", device_get_path(hdp_device->dev));
   1260 
   1261 	hdp_set_mcl_cb(hdp_device, NULL);
   1262 }
   1263 
   1264 static void mcl_disconnected(struct mcap_mcl *mcl, gpointer data)
   1265 {
   1266 	struct hdp_device *hdp_device;
   1267 	GSList *l;
   1268 
   1269 	l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
   1270 	if (!l)
   1271 		return;
   1272 
   1273 	hdp_device = l->data;
   1274 	hdp_device->mcl_conn = FALSE;
   1275 
   1276 	DBG("Mcl disconnected %s", device_get_path(hdp_device->dev));
   1277 }
   1278 
   1279 static void mcl_uncached(struct mcap_mcl *mcl, gpointer data)
   1280 {
   1281 	struct hdp_device *hdp_device;
   1282 	const char *path;
   1283 	GSList *l;
   1284 
   1285 	l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
   1286 	if (!l)
   1287 		return;
   1288 
   1289 	hdp_device = l->data;
   1290 	device_unref_mcl(hdp_device);
   1291 
   1292 	if (hdp_device->sdp_present)
   1293 		return;
   1294 
   1295 	/* Because remote device hasn't announced an HDP record */
   1296 	/* the Bluetooth daemon won't notify when the device shall */
   1297 	/* be removed. Then we have to remove the HealthDevice */
   1298 	/* interface manually */
   1299 	path = device_get_path(hdp_device->dev);
   1300 	g_dbus_unregister_interface(hdp_device->conn, path, HEALTH_DEVICE);
   1301 	DBG("Mcl uncached %s", path);
   1302 }
   1303 
   1304 static void check_devices_mcl(void)
   1305 {
   1306 	struct hdp_device *dev;
   1307 	GSList *l, *to_delete = NULL;
   1308 
   1309 	for (l = devices; l; l = l->next) {
   1310 		dev = l->data;
   1311 		device_unref_mcl(dev);
   1312 
   1313 		if (!dev->sdp_present)
   1314 			to_delete = g_slist_append(to_delete, dev);
   1315 		else
   1316 			remove_channels(dev);
   1317 	}
   1318 
   1319 	for (l = to_delete; l; l = l->next) {
   1320 		const char *path;
   1321 
   1322 		path = device_get_path(dev->dev);
   1323 		g_dbus_unregister_interface(dev->conn, path, HEALTH_DEVICE);
   1324 	}
   1325 
   1326 	g_slist_free(to_delete);
   1327 }
   1328 
   1329 static void release_adapter_instance(struct hdp_adapter *hdp_adapter)
   1330 {
   1331 	if (!hdp_adapter->mi)
   1332 		return;
   1333 
   1334 	check_devices_mcl();
   1335 	mcap_release_instance(hdp_adapter->mi);
   1336 	mcap_instance_unref(hdp_adapter->mi);
   1337 	hdp_adapter->mi = NULL;
   1338 }
   1339 
   1340 static gboolean update_adapter(struct hdp_adapter *hdp_adapter)
   1341 {
   1342 	GError *err = NULL;
   1343 	bdaddr_t addr;
   1344 
   1345 	if (!applications) {
   1346 		release_adapter_instance(hdp_adapter);
   1347 		goto update;
   1348 	}
   1349 
   1350 	if (hdp_adapter->mi)
   1351 		goto update;
   1352 
   1353 	adapter_get_address(hdp_adapter->btd_adapter, &addr);
   1354 	hdp_adapter->mi = mcap_create_instance(&addr, BT_IO_SEC_MEDIUM, 0, 0,
   1355 					mcl_connected, mcl_reconnected,
   1356 					mcl_disconnected, mcl_uncached,
   1357 					NULL, /* CSP is not used by now */
   1358 					hdp_adapter, &err);
   1359 
   1360 	if (!hdp_adapter->mi) {
   1361 		error("Error creating the MCAP instance: %s", err->message);
   1362 		g_error_free(err);
   1363 		return FALSE;
   1364 	}
   1365 
   1366 	hdp_adapter->ccpsm = mcap_get_ctrl_psm(hdp_adapter->mi, &err);
   1367 	if (err) {
   1368 		error("Error getting MCAP control PSM: %s", err->message);
   1369 		goto fail;
   1370 	}
   1371 
   1372 	hdp_adapter->dcpsm = mcap_get_data_psm(hdp_adapter->mi, &err);
   1373 	if (err) {
   1374 		error("Error getting MCAP data PSM: %s", err->message);
   1375 		goto fail;
   1376 	}
   1377 
   1378 update:
   1379 	if (hdp_update_sdp_record(hdp_adapter, applications))
   1380 		return TRUE;
   1381 	error("Error updating the SDP record");
   1382 
   1383 fail:
   1384 	release_adapter_instance(hdp_adapter);
   1385 	if (err)
   1386 		g_error_free(err);
   1387 	return FALSE;
   1388 }
   1389 
   1390 int hdp_adapter_register(DBusConnection *conn, struct btd_adapter *adapter)
   1391 {
   1392 	struct hdp_adapter *hdp_adapter;
   1393 
   1394 	hdp_adapter = g_new0(struct hdp_adapter, 1);
   1395 	hdp_adapter->btd_adapter = btd_adapter_ref(adapter);
   1396 
   1397 	if(!update_adapter(hdp_adapter))
   1398 		goto fail;
   1399 
   1400 	adapters = g_slist_append(adapters, hdp_adapter);
   1401 
   1402 	return 0;
   1403 
   1404 fail:
   1405 	btd_adapter_unref(hdp_adapter->btd_adapter);
   1406 	g_free(hdp_adapter);
   1407 	return -1;
   1408 }
   1409 
   1410 void hdp_adapter_unregister(struct btd_adapter *adapter)
   1411 {
   1412 	struct hdp_adapter *hdp_adapter;
   1413 	GSList *l;
   1414 
   1415 	l = g_slist_find_custom(adapters, adapter, cmp_adapter);
   1416 
   1417 	if (!l)
   1418 		return;
   1419 
   1420 	hdp_adapter = l->data;
   1421 	adapters = g_slist_remove(adapters, hdp_adapter);
   1422 	if (hdp_adapter->sdp_handler)
   1423 		remove_record_from_server(hdp_adapter->sdp_handler);
   1424 	release_adapter_instance(hdp_adapter);
   1425 	btd_adapter_unref(hdp_adapter->btd_adapter);
   1426 	g_free(hdp_adapter);
   1427 }
   1428 
   1429 static void delete_echo_channel_cb(GError *err, gpointer chan)
   1430 {
   1431 	if (err && err->code != MCAP_INVALID_MDL) {
   1432 		/* TODO: Decide if more action is required here */
   1433 		error("Error deleting echo channel: %s", err->message);
   1434 		return;
   1435 	}
   1436 
   1437 	health_channel_destroy(chan);
   1438 }
   1439 
   1440 static void delete_echo_channel(struct hdp_channel *chan)
   1441 {
   1442 	GError *err = NULL;
   1443 
   1444 	if (!chan->dev->mcl_conn) {
   1445 		error("Echo channel cannot be deleted: mcl closed");
   1446 		return;
   1447 	}
   1448 
   1449 	if (mcap_delete_mdl(chan->mdl, delete_echo_channel_cb,
   1450 				hdp_channel_ref(chan),
   1451 				(GDestroyNotify) hdp_channel_unref, &err))
   1452 		return;
   1453 
   1454 	hdp_channel_unref(chan);
   1455 	error("Error deleting the echo channel: %s", err->message);
   1456 	g_error_free(err);
   1457 
   1458 	/* TODO: Decide if more action is required here */
   1459 }
   1460 
   1461 static void abort_echo_channel_cb(GError *err, gpointer data)
   1462 {
   1463 	struct hdp_channel *chan = data;
   1464 
   1465 	if (err && err->code != MCAP_ERROR_INVALID_OPERATION) {
   1466 		error("Aborting error: %s", err->message);
   1467 		if (err->code == MCAP_INVALID_MDL) {
   1468 			/* MDL is removed from MCAP so we can */
   1469 			/* free the data channel without sending */
   1470 			/* a MD_DELETE_MDL_REQ */
   1471 			/* TODO review the above comment */
   1472 			/* hdp_channel_unref(chan); */
   1473 		}
   1474 		return;
   1475 	}
   1476 
   1477 	delete_echo_channel(chan);
   1478 }
   1479 
   1480 static void destroy_create_dc_data(gpointer data)
   1481 {
   1482 	struct hdp_create_dc *dc_data = data;
   1483 
   1484 	hdp_create_data_unref(dc_data);
   1485 }
   1486 
   1487 static void *generate_echo_packet(void)
   1488 {
   1489 	uint8_t *buf;
   1490 	int i;
   1491 
   1492 	buf = g_malloc(HDP_ECHO_LEN);
   1493 	srand(time(NULL));
   1494 
   1495 	for(i = 0; i < HDP_ECHO_LEN; i++)
   1496 		buf[i] = rand() % UINT8_MAX;
   1497 
   1498 	return buf;
   1499 }
   1500 
   1501 static gboolean check_echo(GIOChannel *io_chan, GIOCondition cond,
   1502 								gpointer data)
   1503 {
   1504 	struct hdp_tmp_dc_data *hdp_conn =  data;
   1505 	struct hdp_echo_data *edata = hdp_conn->hdp_chann->edata;
   1506 	struct hdp_channel *chan = hdp_conn->hdp_chann;
   1507 	uint8_t buf[MCAP_DC_MTU];
   1508 	DBusMessage *reply;
   1509 	gboolean value;
   1510 	int fd, len;
   1511 
   1512 	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
   1513 		value = FALSE;
   1514 		goto end;
   1515 	}
   1516 
   1517 	fd = g_io_channel_unix_get_fd(io_chan);
   1518 	len = read(fd, buf, sizeof(buf));
   1519 
   1520 	if (len != HDP_ECHO_LEN) {
   1521 		value = FALSE;
   1522 		goto end;
   1523 	}
   1524 
   1525 	value = (memcmp(buf, edata->buf, len) == 0);
   1526 
   1527 end:
   1528 	reply = g_dbus_create_reply(hdp_conn->msg, DBUS_TYPE_BOOLEAN, &value,
   1529 							DBUS_TYPE_INVALID);
   1530 	g_dbus_send_message(hdp_conn->conn, reply);
   1531 	g_source_remove(edata->tid);
   1532 	edata->tid = 0;
   1533 	g_free(edata->buf);
   1534 	edata->buf = NULL;
   1535 
   1536 	if (!value)
   1537 		close_device_con(chan->dev, FALSE);
   1538 	else
   1539 		delete_echo_channel(chan);
   1540 	hdp_tmp_dc_data_unref(hdp_conn);
   1541 
   1542 	return FALSE;
   1543 }
   1544 
   1545 static gboolean echo_timeout(gpointer data)
   1546 {
   1547 	struct hdp_channel *chan = data;
   1548 	GIOChannel *io;
   1549 	int fd;
   1550 
   1551 	error("Error: Echo request timeout");
   1552 	chan->edata->tid = 0;
   1553 
   1554 	fd = mcap_mdl_get_fd(chan->mdl);
   1555 	if (fd < 0)
   1556 		return FALSE;
   1557 
   1558 	io = g_io_channel_unix_new(fd);
   1559 	g_io_channel_shutdown(io, TRUE, NULL);
   1560 
   1561 	return FALSE;
   1562 }
   1563 
   1564 static void hdp_echo_connect_cb(struct mcap_mdl *mdl, GError *err,
   1565 								gpointer data)
   1566 {
   1567 	struct hdp_tmp_dc_data *hdp_conn =  data;
   1568 	struct hdp_echo_data *edata;
   1569 	GError *gerr = NULL;
   1570 	DBusMessage *reply;
   1571 	GIOChannel *io;
   1572 	int fd;
   1573 
   1574 	if (err) {
   1575 		reply = g_dbus_create_error(hdp_conn->msg,
   1576 						ERROR_INTERFACE ".HealthError",
   1577 						"%s", err->message);
   1578 		g_dbus_send_message(hdp_conn->conn, reply);
   1579 
   1580 		/* Send abort request because remote */
   1581 		/* side is now in PENDING state. */
   1582 		if (!mcap_mdl_abort(hdp_conn->hdp_chann->mdl,
   1583 					abort_echo_channel_cb,
   1584 					hdp_channel_ref(hdp_conn->hdp_chann),
   1585 					(GDestroyNotify) hdp_channel_unref,
   1586 					&gerr)) {
   1587 			error("%s", gerr->message);
   1588 			g_error_free(gerr);
   1589 			hdp_channel_unref(hdp_conn->hdp_chann);
   1590 		}
   1591 		return;
   1592 	}
   1593 
   1594 	fd = mcap_mdl_get_fd(hdp_conn->hdp_chann->mdl);
   1595 	if (fd < 0) {
   1596 		reply = g_dbus_create_error(hdp_conn->msg,
   1597 						ERROR_INTERFACE ".HealthError",
   1598 						"Can't write in echo channel");
   1599 		g_dbus_send_message(hdp_conn->conn, reply);
   1600 		delete_echo_channel(hdp_conn->hdp_chann);
   1601 		return;
   1602 	}
   1603 
   1604 	edata = hdp_conn->hdp_chann->edata;
   1605 	edata->buf = generate_echo_packet();
   1606 	send_echo_data(fd, edata->buf, HDP_ECHO_LEN);
   1607 
   1608 	io = g_io_channel_unix_new(fd);
   1609 	g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN,
   1610 			check_echo, hdp_tmp_dc_data_ref(hdp_conn));
   1611 
   1612 	edata->tid  = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
   1613 					ECHO_TIMEOUT, echo_timeout,
   1614 					hdp_channel_ref(hdp_conn->hdp_chann),
   1615 					(GDestroyNotify) hdp_channel_unref);
   1616 
   1617 	g_io_channel_unref(io);
   1618 }
   1619 
   1620 static void delete_mdl_cb(GError *err, gpointer data)
   1621 {
   1622 	if (err)
   1623 		error("Deleting error: %s", err->message);
   1624 }
   1625 
   1626 static void abort_and_del_mdl_cb(GError *err, gpointer data)
   1627 {
   1628 	struct mcap_mdl *mdl = data;
   1629 	GError *gerr = NULL;
   1630 
   1631 	if (err) {
   1632 		error("%s", err->message);
   1633 		if (err->code == MCAP_INVALID_MDL) {
   1634 			/* MDL is removed from MCAP so we don't */
   1635 			/* need to delete it. */
   1636 			return;
   1637 		}
   1638 	}
   1639 
   1640 	if (!mcap_delete_mdl(mdl, delete_mdl_cb, NULL, NULL, &gerr)) {
   1641 		error("%s", gerr->message);
   1642 		g_error_free(gerr);
   1643 	}
   1644 }
   1645 
   1646 static void hdp_mdl_conn_cb(struct mcap_mdl *mdl, GError *err, gpointer data)
   1647 {
   1648 	struct hdp_tmp_dc_data *hdp_conn =  data;
   1649 	struct hdp_channel *hdp_chann = hdp_conn->hdp_chann;
   1650 	struct hdp_device *dev = hdp_chann->dev;
   1651 	DBusMessage *reply;
   1652 	GError *gerr = NULL;
   1653 
   1654 	if (err) {
   1655 		error("%s", err->message);
   1656 		reply = g_dbus_create_reply(hdp_conn->msg,
   1657 					DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
   1658 					DBUS_TYPE_INVALID);
   1659 		g_dbus_send_message(hdp_conn->conn, reply);
   1660 
   1661 		/* Send abort request because remote side */
   1662 		/* is now in PENDING state */
   1663 		if (!mcap_mdl_abort(hdp_chann->mdl, abort_mdl_cb, hdp_chann,
   1664 								NULL, &gerr)) {
   1665 			error("%s", gerr->message);
   1666 			g_error_free(gerr);
   1667 		}
   1668 		return;
   1669 	}
   1670 
   1671 	reply = g_dbus_create_reply(hdp_conn->msg,
   1672 					DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
   1673 					DBUS_TYPE_INVALID);
   1674 	g_dbus_send_message(hdp_conn->conn, reply);
   1675 
   1676 	if (!check_channel_conf(hdp_chann)) {
   1677 		close_mdl(hdp_chann);
   1678 		return;
   1679 	}
   1680 
   1681 	if (dev->fr)
   1682 		return;
   1683 
   1684 	dev->fr = hdp_channel_ref(hdp_chann);
   1685 
   1686 	if (dev->fr->mdep != HDP_MDEP_ECHO)
   1687 		g_dbus_emit_signal(dev->conn,
   1688 					device_get_path(dev->dev),
   1689 					HEALTH_DEVICE,
   1690 					"ChannelConnected",
   1691 					DBUS_TYPE_OBJECT_PATH, &dev->fr->path,
   1692 					DBUS_TYPE_INVALID);
   1693 
   1694 
   1695 	emit_property_changed(dev->conn, device_get_path(dev->dev),
   1696 					HEALTH_DEVICE, "MainChannel",
   1697 					DBUS_TYPE_OBJECT_PATH, &dev->fr->path);
   1698 }
   1699 
   1700 static void device_create_mdl_cb(struct mcap_mdl *mdl, uint8_t conf,
   1701 						GError *err, gpointer data)
   1702 {
   1703 	struct hdp_create_dc *user_data = data;
   1704 	struct hdp_tmp_dc_data *hdp_conn;
   1705 	struct hdp_channel *hdp_chan;
   1706 	GError *gerr = NULL;
   1707 	DBusMessage *reply;
   1708 
   1709 	if (err) {
   1710 		reply = g_dbus_create_error(user_data->msg,
   1711 					ERROR_INTERFACE ".HealthError",
   1712 					"%s", err->message);
   1713 		g_dbus_send_message(user_data->conn, reply);
   1714 		return;
   1715 	}
   1716 
   1717 	if (user_data->mdep != HDP_MDEP_ECHO &&
   1718 				user_data->config == HDP_NO_PREFERENCE_DC) {
   1719 		if (!user_data->dev->fr && (conf != HDP_RELIABLE_DC)) {
   1720 			g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
   1721 					"Data channel aborted, first data "
   1722 					"channel should be reliable");
   1723 			goto fail;
   1724 		} else if (conf == HDP_NO_PREFERENCE_DC ||
   1725 						conf > HDP_STREAMING_DC) {
   1726 			g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
   1727 							"Data channel aborted, "
   1728 							"configuration error");
   1729 			goto fail;
   1730 		}
   1731 	}
   1732 
   1733 	hdp_chan = create_channel(user_data->dev, conf, mdl,
   1734 							mcap_mdl_get_mdlid(mdl),
   1735 							user_data->app, &gerr);
   1736 	if (!hdp_chan)
   1737 		goto fail;
   1738 
   1739 	hdp_conn = g_new0(struct hdp_tmp_dc_data, 1);
   1740 	hdp_conn->msg = dbus_message_ref(user_data->msg);
   1741 	hdp_conn->conn = dbus_connection_ref(user_data->conn);
   1742 	hdp_conn->hdp_chann = hdp_chan;
   1743 	hdp_conn->cb = user_data->cb;
   1744 	hdp_chan->mdep = user_data->mdep;
   1745 
   1746 	if (hdp_get_dcpsm(hdp_chan->dev, hdp_get_dcpsm_cb,
   1747 						hdp_tmp_dc_data_ref(hdp_conn),
   1748 						hdp_tmp_dc_data_destroy, &gerr))
   1749 		return;
   1750 
   1751 	error("%s", gerr->message);
   1752 	g_error_free(gerr);
   1753 
   1754 	reply = g_dbus_create_reply(hdp_conn->msg,
   1755 					DBUS_TYPE_OBJECT_PATH, &hdp_chan->path,
   1756 					DBUS_TYPE_INVALID);
   1757 	g_dbus_send_message(hdp_conn->conn, reply);
   1758 	hdp_tmp_dc_data_unref(hdp_conn);
   1759 
   1760 	/* Send abort request because remote side is now in PENDING state */
   1761 	if (!mcap_mdl_abort(mdl, abort_mdl_cb, hdp_chan, NULL, &gerr)) {
   1762 		error("%s", gerr->message);
   1763 		g_error_free(gerr);
   1764 	}
   1765 
   1766 	return;
   1767 
   1768 fail:
   1769 	reply = g_dbus_create_error(user_data->msg,
   1770 						ERROR_INTERFACE ".HealthError",
   1771 						"%s", gerr->message);
   1772 	g_dbus_send_message(user_data->conn, reply);
   1773 	g_error_free(gerr);
   1774 
   1775 	/* Send abort request because remote side is now in PENDING */
   1776 	/* state. Then we have to delete it because we couldn't */
   1777 	/* register the HealthChannel interface */
   1778 	if (!mcap_mdl_abort(mdl, abort_and_del_mdl_cb, mcap_mdl_ref(mdl), NULL,
   1779 								&gerr)) {
   1780 		error("%s", gerr->message);
   1781 		g_error_free(gerr);
   1782 		mcap_mdl_unref(mdl);
   1783 	}
   1784 }
   1785 
   1786 static void device_create_dc_cb(gpointer user_data, GError *err)
   1787 {
   1788 	struct hdp_create_dc *data = user_data;
   1789 	DBusMessage *reply;
   1790 	GError *gerr = NULL;
   1791 
   1792 	if (err) {
   1793 		reply = g_dbus_create_error(data->msg,
   1794 					ERROR_INTERFACE ".HealthError",
   1795 					"%s", err->message);
   1796 		g_dbus_send_message(data->conn, reply);
   1797 		return;
   1798 	}
   1799 
   1800 	if (!data->dev->mcl) {
   1801 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
   1802 				"Mcl was closed");
   1803 		goto fail;
   1804 	}
   1805 
   1806 	hdp_create_data_ref(data);
   1807 
   1808 	if (mcap_create_mdl(data->dev->mcl, data->mdep, data->config,
   1809 						device_create_mdl_cb, data,
   1810 						destroy_create_dc_data, &gerr))
   1811 		return;
   1812 	hdp_create_data_unref(data);
   1813 
   1814 fail:
   1815 	reply = g_dbus_create_error(data->msg, ERROR_INTERFACE ".HealthError",
   1816 							"%s", gerr->message);
   1817 	g_error_free(gerr);
   1818 	g_dbus_send_message(data->conn, reply);
   1819 }
   1820 
   1821 static DBusMessage *device_echo(DBusConnection *conn,
   1822 					DBusMessage *msg, void *user_data)
   1823 {
   1824 	struct hdp_device *device = user_data;
   1825 	struct hdp_create_dc *data;
   1826 	DBusMessage *reply;
   1827 	GError *err = NULL;
   1828 
   1829 	data = g_new0(struct hdp_create_dc, 1);
   1830 	data->dev = health_device_ref(device);
   1831 	data->mdep = HDP_MDEP_ECHO;
   1832 	data->config = HDP_RELIABLE_DC;
   1833 	data->msg = dbus_message_ref(msg);
   1834 	data->conn = dbus_connection_ref(conn);
   1835 	data->cb = hdp_echo_connect_cb;
   1836 	hdp_create_data_ref(data);
   1837 
   1838 	if (device->mcl_conn && device->mcl) {
   1839 		if (mcap_create_mdl(device->mcl, data->mdep, data->config,
   1840 						device_create_mdl_cb, data,
   1841 						destroy_create_dc_data, &err))
   1842 			return NULL;
   1843 		goto fail;
   1844 	}
   1845 
   1846 	if (hdp_establish_mcl(data->dev, device_create_dc_cb,
   1847 					data, destroy_create_dc_data, &err))
   1848 		return NULL;
   1849 
   1850 fail:
   1851 	reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
   1852 							"%s", err->message);
   1853 	g_error_free(err);
   1854 	hdp_create_data_unref(data);
   1855 	return reply;
   1856 }
   1857 
   1858 static void device_get_mdep_cb(uint8_t mdep, gpointer data, GError *err)
   1859 {
   1860 	struct hdp_create_dc *dc_data, *user_data = data;
   1861 	DBusMessage *reply;
   1862 	GError *gerr = NULL;
   1863 
   1864 	if (err) {
   1865 		reply = g_dbus_create_error(user_data->msg,
   1866 						ERROR_INTERFACE ".HealthError",
   1867 						"%s", err->message);
   1868 		g_dbus_send_message(user_data->conn, reply);
   1869 		return;
   1870 	}
   1871 
   1872 	dc_data = hdp_create_data_ref(user_data);
   1873 	dc_data->mdep = mdep;
   1874 
   1875 	if (user_data->dev->mcl_conn) {
   1876 		device_create_dc_cb(dc_data, NULL);
   1877 		hdp_create_data_unref(dc_data);
   1878 		return;
   1879 	}
   1880 
   1881 	if (hdp_establish_mcl(dc_data->dev, device_create_dc_cb,
   1882 					dc_data, destroy_create_dc_data, &gerr))
   1883 		return;
   1884 
   1885 	reply = g_dbus_create_error(user_data->msg,
   1886 						ERROR_INTERFACE ".HealthError",
   1887 						"%s", gerr->message);
   1888 	hdp_create_data_unref(dc_data);
   1889 	g_error_free(gerr);
   1890 	g_dbus_send_message(user_data->conn, reply);
   1891 }
   1892 
   1893 static DBusMessage *device_create_channel(DBusConnection *conn,
   1894 					DBusMessage *msg, void *user_data)
   1895 {
   1896 	struct hdp_device *device = user_data;
   1897 	struct hdp_application *app;
   1898 	struct hdp_create_dc *data;
   1899 	char *app_path, *conf;
   1900 	DBusMessage *reply;
   1901 	GError *err = NULL;
   1902 	uint8_t config;
   1903 	GSList *l;
   1904 
   1905 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &app_path,
   1906 							DBUS_TYPE_STRING, &conf,
   1907 							DBUS_TYPE_INVALID))
   1908 		return btd_error_invalid_args(msg);
   1909 
   1910 	l = g_slist_find_custom(applications, app_path, cmp_app);
   1911 	if (!l)
   1912 		return btd_error_invalid_args(msg);
   1913 
   1914 	app = l->data;
   1915 
   1916 	if (g_ascii_strcasecmp("Reliable", conf) == 0)
   1917 		config = HDP_RELIABLE_DC;
   1918 	else if (g_ascii_strcasecmp("Streaming", conf) == 0)
   1919 		config = HDP_STREAMING_DC;
   1920 	else if (g_ascii_strcasecmp("Any", conf) == 0)
   1921 		config = HDP_NO_PREFERENCE_DC;
   1922 	else
   1923 		return btd_error_invalid_args(msg);
   1924 
   1925 	if (app->role == HDP_SINK && config != HDP_NO_PREFERENCE_DC)
   1926 		return btd_error_invalid_args(msg);
   1927 
   1928 	if (app->role == HDP_SOURCE && config == HDP_NO_PREFERENCE_DC)
   1929 		return btd_error_invalid_args(msg);
   1930 
   1931 	if (!device->fr && config == HDP_STREAMING_DC)
   1932 		return btd_error_invalid_args(msg);
   1933 
   1934 	data = g_new0(struct hdp_create_dc, 1);
   1935 	data->dev = health_device_ref(device);
   1936 	data->config = config;
   1937 	data->app = hdp_application_ref(app);
   1938 	data->msg = dbus_message_ref(msg);
   1939 	data->conn = dbus_connection_ref(conn);
   1940 	data->cb = hdp_mdl_conn_cb;
   1941 
   1942 	if (hdp_get_mdep(device, l->data, device_get_mdep_cb,
   1943 						hdp_create_data_ref(data),
   1944 						destroy_create_dc_data, &err))
   1945 		return NULL;
   1946 
   1947 	reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
   1948 							"%s", err->message);
   1949 	g_error_free(err);
   1950 	hdp_create_data_unref(data);
   1951 	return reply;
   1952 }
   1953 
   1954 static void hdp_mdl_delete_cb(GError *err, gpointer data)
   1955 {
   1956 	struct hdp_tmp_dc_data *del_data = data;
   1957 	DBusMessage *reply;
   1958 	char *path;
   1959 
   1960 	if (err && err->code != MCAP_INVALID_MDL) {
   1961 		reply = g_dbus_create_error(del_data->msg,
   1962 						ERROR_INTERFACE ".HealthError",
   1963 						"%s", err->message);
   1964 		g_dbus_send_message(del_data->conn, reply);
   1965 		return;
   1966 	}
   1967 
   1968 	path = g_strdup(del_data->hdp_chann->path);
   1969 	g_dbus_unregister_interface(del_data->conn, path, HEALTH_CHANNEL);
   1970 	g_free(path);
   1971 
   1972 	reply = g_dbus_create_reply(del_data->msg, DBUS_TYPE_INVALID);
   1973 	g_dbus_send_message(del_data->conn, reply);
   1974 }
   1975 
   1976 static void hdp_continue_del_cb(gpointer user_data, GError *err)
   1977 {
   1978 	struct hdp_tmp_dc_data *del_data = user_data;
   1979 	GError *gerr = NULL;
   1980 	DBusMessage *reply;
   1981 
   1982 	if (err) {
   1983 		reply = g_dbus_create_error(del_data->msg,
   1984 					ERROR_INTERFACE ".HealthError",
   1985 					"%s", err->message);
   1986 		g_dbus_send_message(del_data->conn, reply);
   1987 		return;
   1988 	}
   1989 
   1990 	if (mcap_delete_mdl(del_data->hdp_chann->mdl, hdp_mdl_delete_cb,
   1991 						hdp_tmp_dc_data_ref(del_data),
   1992 						hdp_tmp_dc_data_destroy, &gerr))
   1993 			return;
   1994 
   1995 	reply = g_dbus_create_error(del_data->msg,
   1996 						ERROR_INTERFACE ".HealthError",
   1997 						"%s", gerr->message);
   1998 	hdp_tmp_dc_data_unref(del_data);
   1999 	g_error_free(gerr);
   2000 	g_dbus_send_message(del_data->conn, reply);
   2001 }
   2002 
   2003 static DBusMessage *device_destroy_channel(DBusConnection *conn,
   2004 					DBusMessage *msg, void *user_data)
   2005 {
   2006 	struct hdp_device *device = user_data;
   2007 	struct hdp_tmp_dc_data *del_data;
   2008 	struct hdp_channel *hdp_chan;
   2009 	DBusMessage *reply;
   2010 	GError *err = NULL;
   2011 	char *path;
   2012 	GSList *l;
   2013 
   2014 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
   2015 							DBUS_TYPE_INVALID)){
   2016 		return btd_error_invalid_args(msg);
   2017 	}
   2018 
   2019 	l = g_slist_find_custom(device->channels, path, cmp_chan_path);
   2020 	if (!l)
   2021 		return btd_error_invalid_args(msg);
   2022 
   2023 	hdp_chan = l->data;
   2024 	del_data = g_new0(struct hdp_tmp_dc_data, 1);
   2025 	del_data->msg = dbus_message_ref(msg);
   2026 	del_data->conn = dbus_connection_ref(conn);
   2027 	del_data->hdp_chann = hdp_channel_ref(hdp_chan);
   2028 
   2029 	if (device->mcl_conn) {
   2030 		if (mcap_delete_mdl(hdp_chan->mdl, hdp_mdl_delete_cb,
   2031 						hdp_tmp_dc_data_ref(del_data),
   2032 						hdp_tmp_dc_data_destroy, &err))
   2033 			return NULL;
   2034 		goto fail;
   2035 	}
   2036 
   2037 	if (hdp_establish_mcl(device, hdp_continue_del_cb,
   2038 						hdp_tmp_dc_data_ref(del_data),
   2039 						hdp_tmp_dc_data_destroy, &err))
   2040 		return NULL;
   2041 
   2042 fail:
   2043 	reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
   2044 							"%s", err->message);
   2045 	hdp_tmp_dc_data_unref(del_data);
   2046 	g_error_free(err);
   2047 	return reply;
   2048 }
   2049 
   2050 static DBusMessage *device_get_properties(DBusConnection *conn,
   2051 					DBusMessage *msg, void *user_data)
   2052 {
   2053 	struct hdp_device *device = user_data;
   2054 	DBusMessageIter iter, dict;
   2055 	DBusMessage *reply;
   2056 	char *path;
   2057 
   2058 	reply = dbus_message_new_method_return(msg);
   2059 	if (!reply)
   2060 		return NULL;
   2061 
   2062 	dbus_message_iter_init_append(reply, &iter);
   2063 
   2064 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
   2065 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
   2066 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
   2067 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
   2068 
   2069 	if (device->fr)
   2070 		path = g_strdup(device->fr->path);
   2071 	else
   2072 		path = g_strdup("");
   2073 	dict_append_entry(&dict, "MainChannel", DBUS_TYPE_OBJECT_PATH, &path);
   2074 	g_free(path);
   2075 	dbus_message_iter_close_container(&iter, &dict);
   2076 
   2077 	return reply;
   2078 }
   2079 
   2080 static void health_device_destroy(void *data)
   2081 {
   2082 	struct hdp_device *device = data;
   2083 
   2084 	DBG("Unregistered interface %s on path %s", HEALTH_DEVICE,
   2085 						device_get_path(device->dev));
   2086 
   2087 	remove_channels(device);
   2088 	if (device->ndc) {
   2089 		hdp_channel_unref(device->ndc);
   2090 		device->ndc = NULL;
   2091 	}
   2092 
   2093 	devices = g_slist_remove(devices, device);
   2094 	health_device_unref(device);
   2095 }
   2096 
   2097 static GDBusMethodTable health_device_methods[] = {
   2098 	{"Echo",		"",	"b",	device_echo,
   2099 						G_DBUS_METHOD_FLAG_ASYNC },
   2100 	{"CreateChannel",	"os",	"o",	device_create_channel,
   2101 						G_DBUS_METHOD_FLAG_ASYNC },
   2102 	{"DestroyChannel",	"o",	"",	device_destroy_channel,
   2103 						G_DBUS_METHOD_FLAG_ASYNC },
   2104 	{"GetProperties",	"",	"a{sv}", device_get_properties},
   2105 	{ NULL }
   2106 };
   2107 
   2108 static GDBusSignalTable health_device_signals[] = {
   2109 	{"ChannelConnected",		"o"		},
   2110 	{"ChannelDeleted",		"o"		},
   2111 	{"PropertyChanged",		"sv"		},
   2112 	{ NULL }
   2113 };
   2114 
   2115 static struct hdp_device *create_health_device(DBusConnection *conn,
   2116 						struct btd_device *device)
   2117 {
   2118 	struct btd_adapter *adapter = device_get_adapter(device);
   2119 	const gchar *path = device_get_path(device);
   2120 	struct hdp_device *dev;
   2121 	GSList *l;
   2122 
   2123 	if (!device)
   2124 		return NULL;
   2125 
   2126 	dev = g_new0(struct hdp_device, 1);
   2127 	dev->conn = dbus_connection_ref(conn);
   2128 	dev->dev = btd_device_ref(device);
   2129 	health_device_ref(dev);
   2130 
   2131 	l = g_slist_find_custom(adapters, adapter, cmp_adapter);
   2132 	if (!l)
   2133 		goto fail;
   2134 
   2135 	dev->hdp_adapter = l->data;
   2136 
   2137 	if (!g_dbus_register_interface(conn, path,
   2138 					HEALTH_DEVICE,
   2139 					health_device_methods,
   2140 					health_device_signals, NULL,
   2141 					dev, health_device_destroy)) {
   2142 		error("D-Bus failed to register %s interface", HEALTH_DEVICE);
   2143 		goto fail;
   2144 	}
   2145 
   2146 	DBG("Registered interface %s on path %s", HEALTH_DEVICE, path);
   2147 	return dev;
   2148 
   2149 fail:
   2150 	health_device_unref(dev);
   2151 	return NULL;
   2152 }
   2153 
   2154 int hdp_device_register(DBusConnection *conn, struct btd_device *device)
   2155 {
   2156 	struct hdp_device *hdev;
   2157 	GSList *l;
   2158 
   2159 	l = g_slist_find_custom(devices, device, cmp_device);
   2160 	if (l) {
   2161 		hdev = l->data;
   2162 		hdev->sdp_present = TRUE;
   2163 		return 0;
   2164 	}
   2165 
   2166 	hdev = create_health_device(conn, device);
   2167 	if (!hdev)
   2168 		return -1;
   2169 
   2170 	hdev->sdp_present = TRUE;
   2171 
   2172 	devices = g_slist_prepend(devices, hdev);
   2173 	return 0;
   2174 }
   2175 
   2176 void hdp_device_unregister(struct btd_device *device)
   2177 {
   2178 	struct hdp_device *hdp_dev;
   2179 	const char *path;
   2180 	GSList *l;
   2181 
   2182 	l = g_slist_find_custom(devices, device, cmp_device);
   2183 	if (!l)
   2184 		return;
   2185 
   2186 	hdp_dev = l->data;
   2187 	path = device_get_path(hdp_dev->dev);
   2188 	g_dbus_unregister_interface(hdp_dev->conn, path, HEALTH_DEVICE);
   2189 }
   2190 
   2191 int hdp_manager_start(DBusConnection *conn)
   2192 {
   2193 	DBG("Starting Health manager");
   2194 
   2195 	if (!g_dbus_register_interface(conn, MANAGER_PATH,
   2196 					HEALTH_MANAGER,
   2197 					health_manager_methods, NULL, NULL,
   2198 					NULL, manager_path_unregister)) {
   2199 		error("D-Bus failed to register %s interface", HEALTH_MANAGER);
   2200 		return -1;
   2201 	}
   2202 
   2203 	connection = dbus_connection_ref(conn);
   2204 
   2205 	return 0;
   2206 }
   2207 
   2208 void hdp_manager_stop(void)
   2209 {
   2210 	g_dbus_unregister_interface(connection, MANAGER_PATH, HEALTH_MANAGER);
   2211 
   2212 	dbus_connection_unref(connection);
   2213 	DBG("Stopped Health manager");
   2214 }
   2215 
   2216 struct hdp_device *health_device_ref(struct hdp_device *hdp_dev)
   2217 {
   2218 	hdp_dev->ref++;
   2219 
   2220 	DBG("health_device_ref(%p): ref=%d", hdp_dev, hdp_dev->ref);
   2221 
   2222 	return hdp_dev;
   2223 }
   2224 
   2225 void health_device_unref(struct hdp_device *hdp_dev)
   2226 {
   2227 	hdp_dev->ref--;
   2228 
   2229 	DBG("health_device_unref(%p): ref=%d", hdp_dev, hdp_dev->ref);
   2230 
   2231 	if (hdp_dev->ref > 0)
   2232 		return;
   2233 
   2234 	free_health_device(hdp_dev);
   2235 }
   2236