Home | History | Annotate | Download | only in audio
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2006-2007  Nokia Corporation
      6  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <unistd.h>
     32 #include <sys/stat.h>
     33 #include <sys/param.h>
     34 #include <netinet/in.h>
     35 
     36 #include <bluetooth/bluetooth.h>
     37 #include <bluetooth/hci.h>
     38 #include <bluetooth/hci_lib.h>
     39 #include <bluetooth/sdp.h>
     40 #include <bluetooth/sdp_lib.h>
     41 
     42 #include <glib.h>
     43 #include <dbus/dbus.h>
     44 #include <gdbus.h>
     45 
     46 #include "logging.h"
     47 #include "textfile.h"
     48 #include "../src/adapter.h"
     49 #include "../src/device.h"
     50 
     51 #include "error.h"
     52 #include "ipc.h"
     53 #include "dbus-common.h"
     54 #include "device.h"
     55 #include "unix.h"
     56 #include "avdtp.h"
     57 #include "control.h"
     58 #include "headset.h"
     59 #include "gateway.h"
     60 #include "sink.h"
     61 #include "source.h"
     62 
     63 #define AUDIO_INTERFACE "org.bluez.Audio"
     64 
     65 #define CONTROL_CONNECT_TIMEOUT 2
     66 #define AVDTP_CONNECT_TIMEOUT 1
     67 #define HEADSET_CONNECT_TIMEOUT 1
     68 
     69 typedef enum {
     70 	AUDIO_STATE_DISCONNECTED,
     71 	AUDIO_STATE_CONNECTING,
     72 	AUDIO_STATE_CONNECTED,
     73 } audio_state_t;
     74 
     75 struct service_auth {
     76 	service_auth_cb cb;
     77 	void *user_data;
     78 };
     79 
     80 struct dev_priv {
     81 	audio_state_t state;
     82 
     83 	headset_state_t hs_state;
     84 	sink_state_t sink_state;
     85 	avctp_state_t avctp_state;
     86 	GSList *auths;
     87 
     88 	DBusMessage *conn_req;
     89 	DBusMessage *dc_req;
     90 
     91 	guint control_timer;
     92 	guint avdtp_timer;
     93 	guint headset_timer;
     94 
     95 	gboolean authorized;
     96 	guint auth_idle_id;
     97 };
     98 
     99 static unsigned int sink_callback_id = 0;
    100 static unsigned int avctp_callback_id = 0;
    101 static unsigned int avdtp_callback_id = 0;
    102 static unsigned int headset_callback_id = 0;
    103 
    104 static void device_free(struct audio_device *dev)
    105 {
    106 	struct dev_priv *priv = dev->priv;
    107 
    108 	if (dev->conn)
    109 		dbus_connection_unref(dev->conn);
    110 
    111 	btd_device_unref(dev->btd_dev);
    112 
    113 	if (priv) {
    114 		if (priv->control_timer)
    115 			g_source_remove(priv->control_timer);
    116 		if (priv->avdtp_timer)
    117 			g_source_remove(priv->avdtp_timer);
    118 		if (priv->headset_timer)
    119 			g_source_remove(priv->headset_timer);
    120 		if (priv->dc_req)
    121 			dbus_message_unref(priv->dc_req);
    122 		if (priv->conn_req)
    123 			dbus_message_unref(priv->conn_req);
    124 		g_free(priv);
    125 	}
    126 
    127 	g_free(dev->path);
    128 	g_free(dev);
    129 }
    130 
    131 static const char *state2str(audio_state_t state)
    132 {
    133 	switch (state) {
    134 	case AUDIO_STATE_DISCONNECTED:
    135 		return "disconnected";
    136 	case AUDIO_STATE_CONNECTING:
    137 		return "connecting";
    138 	case AUDIO_STATE_CONNECTED:
    139 		return "connected";
    140 	default:
    141 		error("Invalid audio state %d", state);
    142 		return NULL;
    143 	}
    144 }
    145 
    146 static void device_set_state(struct audio_device *dev, audio_state_t new_state)
    147 {
    148 	struct dev_priv *priv = dev->priv;
    149 	const char *state_str;
    150 	DBusMessage *reply = NULL;
    151 
    152 	state_str = state2str(new_state);
    153 	if (!state_str)
    154 		return;
    155 
    156 	if (new_state == AUDIO_STATE_DISCONNECTED)
    157 		priv->authorized = FALSE;
    158 
    159 	if (dev->priv->state == new_state) {
    160 		debug("state change attempted from %s to %s",
    161 							state_str, state_str);
    162 		return;
    163 	}
    164 
    165 	dev->priv->state = new_state;
    166 
    167 	if (priv->dc_req && new_state == AUDIO_STATE_DISCONNECTED) {
    168 		reply = dbus_message_new_method_return(priv->dc_req);
    169 		dbus_message_unref(priv->dc_req);
    170 		priv->dc_req = NULL;
    171 		g_dbus_send_message(dev->conn, reply);
    172 	}
    173 
    174 	if (priv->conn_req && new_state != AUDIO_STATE_CONNECTING) {
    175 		if (new_state == AUDIO_STATE_CONNECTED)
    176 			reply = dbus_message_new_method_return(priv->conn_req);
    177 		else
    178 			reply = g_dbus_create_error(priv->conn_req,
    179 							ERROR_INTERFACE
    180 							".ConnectFailed",
    181 							"Connecting failed");
    182 		dbus_message_unref(priv->conn_req);
    183 		priv->conn_req = NULL;
    184 		g_dbus_send_message(dev->conn, reply);
    185 	}
    186 
    187 	emit_property_changed(dev->conn, dev->path,
    188 				AUDIO_INTERFACE, "State",
    189 				DBUS_TYPE_STRING, &state_str);
    190 }
    191 
    192 static gboolean control_connect_timeout(gpointer user_data)
    193 {
    194 	struct audio_device *dev = user_data;
    195 
    196 	dev->priv->control_timer = 0;
    197 
    198 	if (dev->control)
    199 		avrcp_connect(dev);
    200 
    201 	return FALSE;
    202 }
    203 
    204 static gboolean device_set_control_timer(struct audio_device *dev)
    205 {
    206 	struct dev_priv *priv = dev->priv;
    207 
    208 	if (!dev->control)
    209 		return FALSE;
    210 
    211 	if (priv->control_timer)
    212 		return FALSE;
    213 
    214 	priv->control_timer = g_timeout_add_seconds(CONTROL_CONNECT_TIMEOUT,
    215 							control_connect_timeout,
    216 							dev);
    217 
    218 	return TRUE;
    219 }
    220 
    221 static void device_remove_control_timer(struct audio_device *dev)
    222 {
    223 	if (dev->priv->control_timer)
    224 		g_source_remove(dev->priv->control_timer);
    225 	dev->priv->control_timer = 0;
    226 }
    227 
    228 static gboolean avdtp_connect_timeout(gpointer user_data)
    229 {
    230 	struct audio_device *dev = user_data;
    231 
    232 	dev->priv->avdtp_timer = 0;
    233 
    234 	if (dev->sink) {
    235 		struct avdtp *session = avdtp_get(&dev->src, &dev->dst);
    236 
    237 		if (!session)
    238 			return FALSE;
    239 
    240 		sink_setup_stream(dev->sink, session);
    241 		avdtp_unref(session);
    242 	}
    243 
    244 	return FALSE;
    245 }
    246 
    247 static gboolean device_set_avdtp_timer(struct audio_device *dev)
    248 {
    249 	struct dev_priv *priv = dev->priv;
    250 
    251 	if (!dev->sink)
    252 		return FALSE;
    253 
    254 	if (priv->avdtp_timer)
    255 		return FALSE;
    256 
    257 	priv->avdtp_timer = g_timeout_add_seconds(AVDTP_CONNECT_TIMEOUT,
    258 							avdtp_connect_timeout,
    259 							dev);
    260 
    261 	return TRUE;
    262 }
    263 
    264 static void device_remove_avdtp_timer(struct audio_device *dev)
    265 {
    266 	if (dev->priv->avdtp_timer)
    267 		g_source_remove(dev->priv->avdtp_timer);
    268 	dev->priv->avdtp_timer = 0;
    269 }
    270 
    271 static gboolean headset_connect_timeout(gpointer user_data)
    272 {
    273 	struct audio_device *dev = user_data;
    274 	struct dev_priv *priv = dev->priv;
    275 
    276 	dev->priv->headset_timer = 0;
    277 
    278 	if (dev->headset == NULL)
    279 		return FALSE;
    280 
    281 	if (headset_config_stream(dev, FALSE, NULL, NULL) == 0) {
    282 		if (priv->state != AUDIO_STATE_CONNECTED &&
    283 				(priv->sink_state == SINK_STATE_CONNECTED ||
    284 				priv->sink_state == SINK_STATE_PLAYING))
    285 			device_set_state(dev, AUDIO_STATE_CONNECTED);
    286 	}
    287 
    288 	return FALSE;
    289 }
    290 
    291 static gboolean device_set_headset_timer(struct audio_device *dev)
    292 {
    293 	struct dev_priv *priv = dev->priv;
    294 
    295 	if (!dev->headset)
    296 		return FALSE;
    297 
    298 	if (priv->headset_timer)
    299 		return FALSE;
    300 
    301 	priv->headset_timer = g_timeout_add_seconds(HEADSET_CONNECT_TIMEOUT,
    302 						headset_connect_timeout, dev);
    303 
    304 	return TRUE;
    305 }
    306 
    307 static void device_remove_headset_timer(struct audio_device *dev)
    308 {
    309 	if (dev->priv->headset_timer)
    310 		g_source_remove(dev->priv->headset_timer);
    311 	dev->priv->headset_timer = 0;
    312 }
    313 
    314 static void device_avdtp_cb(struct audio_device *dev, struct avdtp *session,
    315 				avdtp_session_state_t old_state,
    316 				avdtp_session_state_t new_state,
    317 				void *user_data)
    318 {
    319 	if (!dev->sink || !dev->control)
    320 		return;
    321 
    322 	if (new_state == AVDTP_SESSION_STATE_CONNECTED) {
    323 		if (avdtp_stream_setup_active(session))
    324 			device_set_control_timer(dev);
    325 		else
    326 			avrcp_connect(dev);
    327 	}
    328 }
    329 
    330 static void device_sink_cb(struct audio_device *dev,
    331 				sink_state_t old_state,
    332 				sink_state_t new_state,
    333 				void *user_data)
    334 {
    335 	struct dev_priv *priv = dev->priv;
    336 
    337 	if (!dev->sink)
    338 		return;
    339 
    340 	priv->sink_state = new_state;
    341 
    342 	switch (new_state) {
    343 	case SINK_STATE_DISCONNECTED:
    344 		if (dev->control) {
    345 			device_remove_control_timer(dev);
    346 			avrcp_disconnect(dev);
    347 		}
    348 		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
    349 			device_set_state(dev, AUDIO_STATE_DISCONNECTED);
    350 		else if (old_state == SINK_STATE_CONNECTING) {
    351 			switch (priv->hs_state) {
    352 			case HEADSET_STATE_CONNECTED:
    353 			case HEADSET_STATE_PLAY_IN_PROGRESS:
    354 			case HEADSET_STATE_PLAYING:
    355 				device_set_state(dev, AUDIO_STATE_CONNECTED);
    356 			default:
    357 				break;
    358 			}
    359 		}
    360 		break;
    361 	case SINK_STATE_CONNECTING:
    362 		device_remove_avdtp_timer(dev);
    363 		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
    364 			device_set_state(dev, AUDIO_STATE_CONNECTING);
    365 		break;
    366 	case SINK_STATE_CONNECTED:
    367 		if (old_state == SINK_STATE_PLAYING)
    368 			break;
    369 #ifdef ANDROID
    370 		android_set_high_priority(&dev->dst);
    371 #endif
    372 		if (dev->auto_connect) {
    373 			if (!dev->headset)
    374 				device_set_state(dev, AUDIO_STATE_CONNECTED);
    375 			if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
    376 				device_set_headset_timer(dev);
    377 			else if (priv->hs_state == HEADSET_STATE_CONNECTED)
    378 				device_set_state(dev, AUDIO_STATE_CONNECTED);
    379 		} else if (priv->hs_state != HEADSET_STATE_CONNECTED)
    380 			device_set_state(dev, AUDIO_STATE_CONNECTED);
    381 		break;
    382 	case SINK_STATE_PLAYING:
    383 		break;
    384 	}
    385 }
    386 
    387 static void device_avctp_cb(struct audio_device *dev,
    388 				avctp_state_t old_state,
    389 				avctp_state_t new_state,
    390 				void *user_data)
    391 {
    392 	if (!dev->control)
    393 		return;
    394 
    395 	dev->priv->avctp_state = new_state;
    396 
    397 	switch (new_state) {
    398 	case AVCTP_STATE_DISCONNECTED:
    399 		break;
    400 	case AVCTP_STATE_CONNECTING:
    401 		device_remove_control_timer(dev);
    402 		break;
    403 	case AVCTP_STATE_CONNECTED:
    404 		break;
    405 	}
    406 }
    407 
    408 static void device_headset_cb(struct audio_device *dev,
    409 				headset_state_t old_state,
    410 				headset_state_t new_state,
    411 				void *user_data)
    412 {
    413 	struct dev_priv *priv = dev->priv;
    414 
    415 	if (!dev->headset)
    416 		return;
    417 
    418 	priv->hs_state = new_state;
    419 
    420 	switch (new_state) {
    421 	case HEADSET_STATE_DISCONNECTED:
    422 		device_remove_avdtp_timer(dev);
    423 		if (priv->sink_state != SINK_STATE_DISCONNECTED &&
    424 						dev->sink && priv->dc_req) {
    425 			sink_shutdown(dev->sink);
    426 			break;
    427 		}
    428 		if (priv->sink_state == SINK_STATE_DISCONNECTED)
    429 			device_set_state(dev, AUDIO_STATE_DISCONNECTED);
    430 		else if (old_state == HEADSET_STATE_CONNECT_IN_PROGRESS &&
    431 				(priv->sink_state == SINK_STATE_CONNECTED ||
    432 				priv->sink_state == SINK_STATE_PLAYING))
    433 			device_set_state(dev, AUDIO_STATE_CONNECTED);
    434 		break;
    435 	case HEADSET_STATE_CONNECT_IN_PROGRESS:
    436 		device_remove_headset_timer(dev);
    437 		if (priv->sink_state == SINK_STATE_DISCONNECTED)
    438 			device_set_state(dev, AUDIO_STATE_CONNECTING);
    439 		break;
    440 	case HEADSET_STATE_CONNECTED:
    441 		if (old_state == HEADSET_STATE_CONNECTED ||
    442 				old_state == HEADSET_STATE_PLAY_IN_PROGRESS ||
    443 				old_state == HEADSET_STATE_PLAYING)
    444 			break;
    445 		if (dev->auto_connect) {
    446 			if (!dev->sink)
    447 				device_set_state(dev, AUDIO_STATE_CONNECTED);
    448 			else if (priv->sink_state == SINK_STATE_DISCONNECTED)
    449 				device_set_avdtp_timer(dev);
    450 			else if (priv->sink_state == SINK_STATE_CONNECTED)
    451 				device_set_state(dev, AUDIO_STATE_CONNECTED);
    452 		} else if (priv->sink_state != SINK_STATE_CONNECTED)
    453 			device_set_state(dev, AUDIO_STATE_CONNECTED);
    454 		break;
    455 	case HEADSET_STATE_PLAY_IN_PROGRESS:
    456 		break;
    457 	case HEADSET_STATE_PLAYING:
    458 		break;
    459 	}
    460 }
    461 
    462 static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
    463 								void *data)
    464 {
    465 	struct audio_device *dev = data;
    466 	struct dev_priv *priv = dev->priv;
    467 
    468 	if (priv->state == AUDIO_STATE_CONNECTING)
    469 		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
    470 						"Connect in Progress");
    471 	else if (priv->state == AUDIO_STATE_CONNECTED)
    472 		return g_dbus_create_error(msg, ERROR_INTERFACE
    473 						".AlreadyConnected",
    474 						"Already Connected");
    475 
    476 	dev->auto_connect = TRUE;
    477 
    478 	if (dev->headset)
    479 		headset_config_stream(dev, FALSE, NULL, NULL);
    480 
    481 	if (priv->state != AUDIO_STATE_CONNECTING && dev->sink) {
    482 		struct avdtp *session = avdtp_get(&dev->src, &dev->dst);
    483 
    484 		if (!session)
    485 			return g_dbus_create_error(msg, ERROR_INTERFACE
    486 					".Failed",
    487 					"Failed to get AVDTP session");
    488 
    489 		sink_setup_stream(dev->sink, session);
    490 		avdtp_unref(session);
    491 	}
    492 
    493 	/* The previous calls should cause a call to the state callback to
    494 	 * indicate AUDIO_STATE_CONNECTING */
    495 	if (priv->state != AUDIO_STATE_CONNECTING)
    496 		return g_dbus_create_error(msg, ERROR_INTERFACE
    497 				".ConnectFailed",
    498 				"Headset connect failed");
    499 
    500 	priv->conn_req = dbus_message_ref(msg);
    501 
    502 	return NULL;
    503 }
    504 
    505 static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
    506 								void *data)
    507 {
    508 	struct audio_device *dev = data;
    509 	struct dev_priv *priv = dev->priv;
    510 
    511 	if (priv->state == AUDIO_STATE_DISCONNECTED)
    512 		return g_dbus_create_error(msg, ERROR_INTERFACE ".NotConnected",
    513 						"Not connected");
    514 
    515 	if (priv->dc_req)
    516 		return dbus_message_new_method_return(msg);
    517 
    518 	priv->dc_req = dbus_message_ref(msg);
    519 
    520 	if (priv->hs_state != HEADSET_STATE_DISCONNECTED)
    521 		headset_shutdown(dev);
    522 	else if (dev->sink && priv->sink_state != SINK_STATE_DISCONNECTED)
    523 		sink_shutdown(dev->sink);
    524 	else {
    525 		dbus_message_unref(priv->dc_req);
    526 		priv->dc_req = NULL;
    527 		return dbus_message_new_method_return(msg);
    528 	}
    529 
    530 	return NULL;
    531 }
    532 
    533 static DBusMessage *dev_get_properties(DBusConnection *conn, DBusMessage *msg,
    534 								void *data)
    535 {
    536 	struct audio_device *device = data;
    537 	DBusMessage *reply;
    538 	DBusMessageIter iter;
    539 	DBusMessageIter dict;
    540 	const char *state;
    541 
    542 	reply = dbus_message_new_method_return(msg);
    543 	if (!reply)
    544 		return NULL;
    545 
    546 	dbus_message_iter_init_append(reply, &iter);
    547 
    548 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    549 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    550 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    551 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    552 
    553 	/* State */
    554 	state = state2str(device->priv->state);
    555 	if (state)
    556 		dict_append_entry(&dict, "State", DBUS_TYPE_STRING, &state);
    557 
    558 	dbus_message_iter_close_container(&iter, &dict);
    559 
    560 	return reply;
    561 }
    562 
    563 static GDBusMethodTable dev_methods[] = {
    564 	{ "Connect",		"",	"",	dev_connect,
    565 						G_DBUS_METHOD_FLAG_ASYNC },
    566 	{ "Disconnect",		"",	"",	dev_disconnect },
    567 	{ "GetProperties",	"",	"a{sv}",dev_get_properties },
    568 	{ NULL, NULL, NULL, NULL }
    569 };
    570 
    571 static GDBusSignalTable dev_signals[] = {
    572 	{ "PropertyChanged",		"sv"	},
    573 	{ NULL, NULL }
    574 };
    575 
    576 struct audio_device *audio_device_register(DBusConnection *conn,
    577 					struct btd_device *device,
    578 					const char *path, const bdaddr_t *src,
    579 					const bdaddr_t *dst)
    580 {
    581 	struct audio_device *dev;
    582 
    583 	if (!conn || !path)
    584 		return NULL;
    585 
    586 	dev = g_new0(struct audio_device, 1);
    587 
    588 	dev->btd_dev = btd_device_ref(device);
    589 	dev->path = g_strdup(path);
    590 	bacpy(&dev->dst, dst);
    591 	bacpy(&dev->src, src);
    592 	dev->conn = dbus_connection_ref(conn);
    593 	dev->priv = g_new0(struct dev_priv, 1);
    594 	dev->priv->state = AUDIO_STATE_DISCONNECTED;
    595 
    596 	if (!g_dbus_register_interface(dev->conn, dev->path,
    597 					AUDIO_INTERFACE,
    598 					dev_methods, dev_signals, NULL,
    599 					dev, NULL)) {
    600 		error("Unable to register %s on %s", AUDIO_INTERFACE,
    601 								dev->path);
    602 		device_free(dev);
    603 		return NULL;
    604 	}
    605 
    606 	debug("Registered interface %s on path %s", AUDIO_INTERFACE,
    607 								dev->path);
    608 
    609 	if (sink_callback_id == 0)
    610 		sink_callback_id = sink_add_state_cb(device_sink_cb, NULL);
    611 
    612 	if (avdtp_callback_id == 0)
    613 		avdtp_callback_id = avdtp_add_state_cb(device_avdtp_cb, NULL);
    614 	if (avctp_callback_id == 0)
    615 		avctp_callback_id = avctp_add_state_cb(device_avctp_cb, NULL);
    616 
    617 	if (headset_callback_id == 0)
    618 		headset_callback_id = headset_add_state_cb(device_headset_cb,
    619 									NULL);
    620 
    621 	return dev;
    622 }
    623 
    624 gboolean audio_device_is_active(struct audio_device *dev,
    625 						const char *interface)
    626 {
    627 	if (!interface) {
    628 		if ((dev->sink || dev->source) &&
    629 			avdtp_is_connected(&dev->src, &dev->dst))
    630 			return TRUE;
    631 
    632 		if (dev->headset && headset_is_active(dev))
    633 			return TRUE;
    634 	}
    635 	else if (!strcmp(interface, AUDIO_SINK_INTERFACE) && dev->sink &&
    636 			avdtp_is_connected(&dev->src, &dev->dst))
    637 		return TRUE;
    638 	else if (!strcmp(interface, AUDIO_SOURCE_INTERFACE) && dev->source &&
    639 			avdtp_is_connected(&dev->src, &dev->dst))
    640 		return TRUE;
    641 	else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset &&
    642 			headset_is_active(dev))
    643 		return TRUE;
    644 	else if (!strcmp(interface, AUDIO_CONTROL_INTERFACE) && dev->control &&
    645 			control_is_active(dev))
    646 		return TRUE;
    647 	else if (!strcmp(interface, AUDIO_GATEWAY_INTERFACE) && dev->gateway &&
    648 			gateway_is_connected(dev))
    649 		return TRUE;
    650 
    651 	return FALSE;
    652 }
    653 
    654 void audio_device_unregister(struct audio_device *device)
    655 {
    656 	unix_device_removed(device);
    657 
    658 	if (device->headset)
    659 		headset_unregister(device);
    660 
    661 	if (device->sink)
    662 		sink_unregister(device);
    663 
    664 	if (device->source)
    665 		source_unregister(device);
    666 
    667 	if (device->control)
    668 		control_unregister(device);
    669 
    670 	g_dbus_unregister_interface(device->conn, device->path,
    671 						AUDIO_INTERFACE);
    672 
    673 	device_free(device);
    674 }
    675 
    676 static void auth_cb(DBusError *derr, void *user_data)
    677 {
    678 	struct audio_device *dev = user_data;
    679 	struct dev_priv *priv = dev->priv;
    680 
    681 	if (derr == NULL)
    682 		priv->authorized = TRUE;
    683 
    684 	while (priv->auths) {
    685 		struct service_auth *auth = priv->auths->data;
    686 
    687 		auth->cb(derr, auth->user_data);
    688 		priv->auths = g_slist_remove(priv->auths, auth);
    689 		g_free(auth);
    690 	}
    691 }
    692 
    693 static gboolean auth_idle_cb(gpointer user_data)
    694 {
    695 	struct audio_device *dev = user_data;
    696 	struct dev_priv *priv = dev->priv;
    697 
    698 	priv->auth_idle_id = 0;
    699 
    700 	auth_cb(NULL, dev);
    701 
    702 	return FALSE;
    703 }
    704 
    705 static gboolean audio_device_is_connected(struct audio_device *dev)
    706 {
    707 	if (dev->headset) {
    708 		headset_state_t state = headset_get_state(dev);
    709 
    710 		if (state == HEADSET_STATE_CONNECTED ||
    711 				state == HEADSET_STATE_PLAY_IN_PROGRESS ||
    712 				state == HEADSET_STATE_PLAYING)
    713 			return TRUE;
    714 	}
    715 
    716 	if (dev->sink) {
    717 		sink_state_t state = sink_get_state(dev);
    718 
    719 		if (state == SINK_STATE_CONNECTED ||
    720 				state == SINK_STATE_PLAYING)
    721 			return TRUE;
    722 	}
    723 
    724 	if (dev->source) {
    725 		source_state_t state = source_get_state(dev);
    726 
    727 		if (state == SOURCE_STATE_CONNECTED ||
    728 				state == SOURCE_STATE_PLAYING)
    729 			return TRUE;
    730 	}
    731 
    732 	return FALSE;
    733 }
    734 
    735 int audio_device_request_authorization(struct audio_device *dev,
    736 					const char *uuid, service_auth_cb cb,
    737 					void *user_data)
    738 {
    739 	struct dev_priv *priv = dev->priv;
    740 	struct service_auth *auth;
    741 	int err;
    742 
    743 	auth = g_try_new0(struct service_auth, 1);
    744 	if (!auth)
    745 		return -ENOMEM;
    746 
    747 	auth->cb = cb;
    748 	auth->user_data = user_data;
    749 
    750 	priv->auths = g_slist_append(priv->auths, auth);
    751 	if (g_slist_length(priv->auths) > 1)
    752 		return 0;
    753 
    754 	if (priv->authorized || audio_device_is_connected(dev)) {
    755 		priv->auth_idle_id = g_idle_add(auth_idle_cb, dev);
    756 		return 0;
    757 	}
    758 
    759 	err = btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb,
    760 					dev);
    761 	if (err < 0) {
    762 		priv->auths = g_slist_remove(priv->auths, auth);
    763 		g_free(auth);
    764 	}
    765 
    766 	return err;
    767 }
    768 
    769 int audio_device_cancel_authorization(struct audio_device *dev,
    770 					authorization_cb cb, void *user_data)
    771 {
    772 	struct dev_priv *priv = dev->priv;
    773 	GSList *l, *next;
    774 
    775 	for (l = priv->auths; l != NULL; l = next) {
    776 		struct service_auth *auth = priv->auths->data;
    777 
    778 		next = g_slist_next(l);
    779 
    780 		if (cb && auth->cb != cb)
    781 			continue;
    782 
    783 		if (user_data && auth->user_data != user_data)
    784 			continue;
    785 
    786 		priv->auths = g_slist_remove(priv->auths, auth);
    787 		g_free(auth);
    788 	}
    789 
    790 	if (g_slist_length(priv->auths) == 0) {
    791 		if (priv->auth_idle_id > 0) {
    792 			g_source_remove(priv->auth_idle_id);
    793 			priv->auth_idle_id = 0;
    794 		} else
    795 			btd_cancel_authorization(&dev->src, &dev->dst);
    796 	}
    797 
    798 	return 0;
    799 }
    800