Home | History | Annotate | Download | only in audio
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2006-2010  Nokia Corporation
      6  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *  Copyright (C) 2009  Joao Paulo Rechi Vita
      8  *
      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 #ifdef HAVE_CONFIG_H
     27 #include <config.h>
     28 #endif
     29 
     30 #include <stdint.h>
     31 #include <errno.h>
     32 
     33 #include <bluetooth/bluetooth.h>
     34 #include <bluetooth/sdp.h>
     35 
     36 #include <glib.h>
     37 #include <dbus/dbus.h>
     38 #include <gdbus.h>
     39 
     40 #include "log.h"
     41 
     42 #include "device.h"
     43 #include "avdtp.h"
     44 #include "media.h"
     45 #include "a2dp.h"
     46 #include "error.h"
     47 #include "source.h"
     48 #include "dbus-common.h"
     49 #include "../src/adapter.h"
     50 #include "../src/device.h"
     51 
     52 #define STREAM_SETUP_RETRY_TIMER 2
     53 
     54 struct pending_request {
     55 	DBusConnection *conn;
     56 	DBusMessage *msg;
     57 	unsigned int id;
     58 };
     59 
     60 struct source {
     61 	struct audio_device *dev;
     62 	struct avdtp *session;
     63 	struct avdtp_stream *stream;
     64 	unsigned int cb_id;
     65 	guint retry_id;
     66 	avdtp_session_state_t session_state;
     67 	avdtp_state_t stream_state;
     68 	source_state_t state;
     69 	struct pending_request *connect;
     70 	struct pending_request *disconnect;
     71 	DBusConnection *conn;
     72 };
     73 
     74 struct source_state_callback {
     75 	source_state_cb cb;
     76 	void *user_data;
     77 	unsigned int id;
     78 };
     79 
     80 static GSList *source_callbacks = NULL;
     81 
     82 static unsigned int avdtp_callback_id = 0;
     83 
     84 static const char *state2str(source_state_t state)
     85 {
     86 	switch (state) {
     87 	case SOURCE_STATE_DISCONNECTED:
     88 		return "disconnected";
     89 	case SOURCE_STATE_CONNECTING:
     90 		return "connecting";
     91 	case SOURCE_STATE_CONNECTED:
     92 		return "connected";
     93 	case SOURCE_STATE_PLAYING:
     94 		return "playing";
     95 	default:
     96 		error("Invalid source state %d", state);
     97 		return NULL;
     98 	}
     99 }
    100 
    101 static void source_set_state(struct audio_device *dev, source_state_t new_state)
    102 {
    103 	struct source *source = dev->source;
    104 	const char *state_str;
    105 	source_state_t old_state = source->state;
    106 	GSList *l;
    107 
    108 	source->state = new_state;
    109 
    110 	state_str = state2str(new_state);
    111 	if (state_str)
    112 		emit_property_changed(dev->conn, dev->path,
    113 					AUDIO_SOURCE_INTERFACE, "State",
    114 					DBUS_TYPE_STRING, &state_str);
    115 
    116 	for (l = source_callbacks; l != NULL; l = l->next) {
    117 		struct source_state_callback *cb = l->data;
    118 		cb->cb(dev, old_state, new_state, cb->user_data);
    119 	}
    120 }
    121 
    122 static void avdtp_state_callback(struct audio_device *dev,
    123 					struct avdtp *session,
    124 					avdtp_session_state_t old_state,
    125 					avdtp_session_state_t new_state,
    126 					void *user_data)
    127 {
    128 	struct source *source = dev->source;
    129 
    130 	if (source == NULL)
    131 		return;
    132 
    133 	switch (new_state) {
    134 	case AVDTP_SESSION_STATE_DISCONNECTED:
    135 		source_set_state(dev, SOURCE_STATE_DISCONNECTED);
    136 		break;
    137 	case AVDTP_SESSION_STATE_CONNECTING:
    138 		source_set_state(dev, SOURCE_STATE_CONNECTING);
    139 		break;
    140 	case AVDTP_SESSION_STATE_CONNECTED:
    141 		break;
    142 	}
    143 
    144 	source->session_state = new_state;
    145 }
    146 
    147 static void pending_request_free(struct audio_device *dev,
    148 					struct pending_request *pending)
    149 {
    150 	if (pending->conn)
    151 		dbus_connection_unref(pending->conn);
    152 	if (pending->msg)
    153 		dbus_message_unref(pending->msg);
    154 	if (pending->id)
    155 		a2dp_cancel(dev, pending->id);
    156 
    157 	g_free(pending);
    158 }
    159 
    160 static void stream_state_changed(struct avdtp_stream *stream,
    161 					avdtp_state_t old_state,
    162 					avdtp_state_t new_state,
    163 					struct avdtp_error *err,
    164 					void *user_data)
    165 {
    166 	struct audio_device *dev = user_data;
    167 	struct source *source = dev->source;
    168 
    169 	if (err)
    170 		return;
    171 
    172 	switch (new_state) {
    173 	case AVDTP_STATE_IDLE:
    174 		if (source->disconnect) {
    175 			DBusMessage *reply;
    176 			struct pending_request *p;
    177 
    178 			p = source->disconnect;
    179 			source->disconnect = NULL;
    180 
    181 			reply = dbus_message_new_method_return(p->msg);
    182 			g_dbus_send_message(p->conn, reply);
    183 			pending_request_free(dev, p);
    184 		}
    185 
    186 		if (source->session) {
    187 			avdtp_unref(source->session);
    188 			source->session = NULL;
    189 		}
    190 		source->stream = NULL;
    191 		source->cb_id = 0;
    192 		break;
    193 	case AVDTP_STATE_OPEN:
    194 		source_set_state(dev, SOURCE_STATE_CONNECTED);
    195 		break;
    196 	case AVDTP_STATE_STREAMING:
    197 		source_set_state(dev, SOURCE_STATE_PLAYING);
    198 		break;
    199 	case AVDTP_STATE_CONFIGURED:
    200 	case AVDTP_STATE_CLOSING:
    201 	case AVDTP_STATE_ABORTING:
    202 	default:
    203 		break;
    204 	}
    205 
    206 	source->stream_state = new_state;
    207 }
    208 
    209 static void error_failed(DBusConnection *conn, DBusMessage *msg,
    210 							const char *desc)
    211 {
    212 	DBusMessage *reply = btd_error_failed(msg, desc);
    213 	g_dbus_send_message(conn, reply);
    214 }
    215 
    216 static gboolean stream_setup_retry(gpointer user_data)
    217 {
    218 	struct source *source = user_data;
    219 	struct pending_request *pending = source->connect;
    220 
    221 	source->retry_id = 0;
    222 
    223 	if (source->stream_state >= AVDTP_STATE_OPEN) {
    224 		DBG("Stream successfully created, after XCASE connect:connect");
    225 		if (pending->msg) {
    226 			DBusMessage *reply;
    227 			reply = dbus_message_new_method_return(pending->msg);
    228 			g_dbus_send_message(pending->conn, reply);
    229 		}
    230 	} else {
    231 		DBG("Stream setup failed, after XCASE connect:connect");
    232 		if (pending->msg)
    233 			error_failed(pending->conn, pending->msg, "Stream setup failed");
    234 	}
    235 
    236 	source->connect = NULL;
    237 	pending_request_free(source->dev, pending);
    238 
    239 	return FALSE;
    240 }
    241 
    242 static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
    243 					struct avdtp_stream *stream,
    244 					struct avdtp_error *err, void *user_data)
    245 {
    246 	struct source *source = user_data;
    247 	struct pending_request *pending;
    248 
    249 	pending = source->connect;
    250 
    251 	pending->id = 0;
    252 
    253 	if (stream) {
    254 		DBG("Stream successfully created");
    255 
    256 		if (pending->msg) {
    257 			DBusMessage *reply;
    258 			reply = dbus_message_new_method_return(pending->msg);
    259 			g_dbus_send_message(pending->conn, reply);
    260 		}
    261 
    262 		source->connect = NULL;
    263 		pending_request_free(source->dev, pending);
    264 
    265 		return;
    266 	}
    267 
    268 	avdtp_unref(source->session);
    269 	source->session = NULL;
    270 	if (avdtp_error_category(err) == AVDTP_ERRNO
    271 			&& avdtp_error_posix_errno(err) != EHOSTDOWN) {
    272 		DBG("connect:connect XCASE detected");
    273 		source->retry_id = g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
    274 							stream_setup_retry,
    275 							source);
    276 	} else {
    277 		if (pending->msg)
    278 			error_failed(pending->conn, pending->msg, "Stream setup failed");
    279 		source->connect = NULL;
    280 		pending_request_free(source->dev, pending);
    281 		DBG("Stream setup failed : %s", avdtp_strerror(err));
    282 	}
    283 }
    284 
    285 static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
    286 			GSList *caps, void *user_data)
    287 {
    288 	struct source *source = user_data;
    289 	struct pending_request *pending;
    290 	int id;
    291 
    292 	pending = source->connect;
    293 
    294 	pending->id = 0;
    295 
    296 	if (caps == NULL)
    297 		goto failed;
    298 
    299 	id = a2dp_config(session, sep, stream_setup_complete, caps, source);
    300 	if (id == 0)
    301 		goto failed;
    302 
    303 	pending->id = id;
    304 	return;
    305 
    306 failed:
    307 	if (pending->msg)
    308 		error_failed(pending->conn, pending->msg, "Stream setup failed");
    309 	pending_request_free(source->dev, pending);
    310 	source->connect = NULL;
    311 	avdtp_unref(source->session);
    312 	source->session = NULL;
    313 }
    314 
    315 static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err,
    316 				void *user_data)
    317 {
    318 	struct source *source = user_data;
    319 	struct pending_request *pending;
    320 	int id;
    321 
    322 	pending = source->connect;
    323 
    324 	if (err) {
    325 		avdtp_unref(source->session);
    326 		source->session = NULL;
    327 		if (avdtp_error_category(err) == AVDTP_ERRNO
    328 				&& avdtp_error_posix_errno(err) != EHOSTDOWN) {
    329 			DBG("connect:connect XCASE detected");
    330 			source->retry_id =
    331 				g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
    332 							stream_setup_retry,
    333 							source);
    334 		} else
    335 			goto failed;
    336 		return;
    337 	}
    338 
    339 	DBG("Discovery complete");
    340 
    341 	id = a2dp_select_capabilities(source->session, AVDTP_SEP_TYPE_SOURCE, NULL,
    342 						select_complete, source);
    343 	if (id == 0)
    344 		goto failed;
    345 
    346 	pending->id = id;
    347 	return;
    348 
    349 failed:
    350 	if (pending->msg)
    351 		error_failed(pending->conn, pending->msg, "Stream setup failed");
    352 	pending_request_free(source->dev, pending);
    353 	source->connect = NULL;
    354 	avdtp_unref(source->session);
    355 	source->session = NULL;
    356 }
    357 
    358 gboolean source_setup_stream(struct source *source, struct avdtp *session)
    359 {
    360 	if (source->connect || source->disconnect)
    361 		return FALSE;
    362 
    363 	if (session && !source->session)
    364 		source->session = avdtp_ref(session);
    365 
    366 	if (!source->session)
    367 		return FALSE;
    368 
    369 	avdtp_set_auto_disconnect(source->session, FALSE);
    370 
    371 	if (avdtp_discover(source->session, discovery_complete, source) < 0)
    372 		return FALSE;
    373 
    374 	source->connect = g_new0(struct pending_request, 1);
    375 
    376 	return TRUE;
    377 }
    378 
    379 static DBusMessage *source_connect(DBusConnection *conn,
    380 				DBusMessage *msg, void *data)
    381 {
    382 	struct audio_device *dev = data;
    383 	struct source *source = dev->source;
    384 	struct pending_request *pending;
    385 
    386 	if (!source->session)
    387 		source->session = avdtp_get(&dev->src, &dev->dst);
    388 
    389 	if (!source->session)
    390 		return btd_error_failed(msg, "Unable to get a session");
    391 
    392 	if (source->connect || source->disconnect)
    393 		return btd_error_busy(msg);
    394 
    395 	if (source->stream_state >= AVDTP_STATE_OPEN)
    396 		return btd_error_already_connected(msg);
    397 
    398 	if (!source_setup_stream(source, NULL))
    399 		return btd_error_failed(msg, "Failed to create a stream");
    400 
    401 	dev->auto_connect = FALSE;
    402 
    403 	pending = source->connect;
    404 
    405 	pending->conn = dbus_connection_ref(conn);
    406 	pending->msg = dbus_message_ref(msg);
    407 
    408 	DBG("stream creation in progress");
    409 
    410 	return NULL;
    411 }
    412 
    413 static DBusMessage *source_disconnect(DBusConnection *conn,
    414 					DBusMessage *msg, void *data)
    415 {
    416 	struct audio_device *device = data;
    417 	struct source *source = device->source;
    418 	struct pending_request *pending;
    419 	int err;
    420 
    421 	if (!source->session)
    422 		return btd_error_not_connected(msg);
    423 
    424 	if (source->connect || source->disconnect)
    425 		return btd_error_busy(msg);
    426 
    427 	if (source->stream_state < AVDTP_STATE_OPEN) {
    428 		DBusMessage *reply = dbus_message_new_method_return(msg);
    429 		if (!reply)
    430 			return NULL;
    431 		avdtp_unref(source->session);
    432 		source->session = NULL;
    433 		return reply;
    434 	}
    435 
    436 	err = avdtp_close(source->session, source->stream, FALSE);
    437 	if (err < 0)
    438 		return btd_error_failed(msg, strerror(-err));
    439 
    440 	pending = g_new0(struct pending_request, 1);
    441 	pending->conn = dbus_connection_ref(conn);
    442 	pending->msg = dbus_message_ref(msg);
    443 	source->disconnect = pending;
    444 
    445 	return NULL;
    446 }
    447 
    448 static DBusMessage *source_get_properties(DBusConnection *conn,
    449 					DBusMessage *msg, void *data)
    450 {
    451 	struct audio_device *device = data;
    452 	struct source *source = device->source;
    453 	DBusMessage *reply;
    454 	DBusMessageIter iter;
    455 	DBusMessageIter dict;
    456 	const char *state;
    457 
    458 	reply = dbus_message_new_method_return(msg);
    459 	if (!reply)
    460 		return NULL;
    461 
    462 	dbus_message_iter_init_append(reply, &iter);
    463 
    464 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    465 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    466 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    467 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    468 
    469 	/* State */
    470 	state = state2str(source->state);
    471 	if (state)
    472 		dict_append_entry(&dict, "State", DBUS_TYPE_STRING, &state);
    473 
    474 	dbus_message_iter_close_container(&iter, &dict);
    475 
    476 	return reply;
    477 }
    478 
    479 static GDBusMethodTable source_methods[] = {
    480 	{ "Connect",		"",	"",	source_connect,
    481 						G_DBUS_METHOD_FLAG_ASYNC },
    482 	{ "Disconnect",		"",	"",	source_disconnect,
    483 						G_DBUS_METHOD_FLAG_ASYNC },
    484 	{ "GetProperties",	"",	"a{sv}",source_get_properties },
    485 	{ NULL, NULL, NULL, NULL }
    486 };
    487 
    488 static GDBusSignalTable source_signals[] = {
    489 	{ "PropertyChanged",		"sv"	},
    490 	{ NULL, NULL }
    491 };
    492 
    493 static void source_free(struct audio_device *dev)
    494 {
    495 	struct source *source = dev->source;
    496 
    497 	if (source->cb_id)
    498 		avdtp_stream_remove_cb(source->session, source->stream,
    499 					source->cb_id);
    500 
    501 	if (source->session)
    502 		avdtp_unref(source->session);
    503 
    504 	if (source->connect)
    505 		pending_request_free(dev, source->connect);
    506 
    507 	if (source->disconnect)
    508 		pending_request_free(dev, source->disconnect);
    509 
    510 	if (source->retry_id)
    511 		g_source_remove(source->retry_id);
    512 
    513 	g_free(source);
    514 	dev->source = NULL;
    515 }
    516 
    517 static void path_unregister(void *data)
    518 {
    519 	struct audio_device *dev = data;
    520 
    521 	DBG("Unregistered interface %s on path %s",
    522 		AUDIO_SOURCE_INTERFACE, dev->path);
    523 
    524 	source_free(dev);
    525 }
    526 
    527 void source_unregister(struct audio_device *dev)
    528 {
    529 	g_dbus_unregister_interface(dev->conn, dev->path,
    530 		AUDIO_SOURCE_INTERFACE);
    531 }
    532 
    533 struct source *source_init(struct audio_device *dev)
    534 {
    535 	struct source *source;
    536 
    537 	if (!g_dbus_register_interface(dev->conn, dev->path,
    538 					AUDIO_SOURCE_INTERFACE,
    539 					source_methods, source_signals, NULL,
    540 					dev, path_unregister))
    541 		return NULL;
    542 
    543 	DBG("Registered interface %s on path %s",
    544 		AUDIO_SOURCE_INTERFACE, dev->path);
    545 
    546 	if (avdtp_callback_id == 0)
    547 		avdtp_callback_id = avdtp_add_state_cb(avdtp_state_callback,
    548 									NULL);
    549 
    550 	source = g_new0(struct source, 1);
    551 
    552 	source->dev = dev;
    553 
    554 	return source;
    555 }
    556 
    557 gboolean source_is_active(struct audio_device *dev)
    558 {
    559 	struct source *source = dev->source;
    560 
    561 	if (source->session)
    562 		return TRUE;
    563 
    564 	return FALSE;
    565 }
    566 
    567 avdtp_state_t source_get_state(struct audio_device *dev)
    568 {
    569 	struct source *source = dev->source;
    570 
    571 	return source->stream_state;
    572 }
    573 
    574 gboolean source_new_stream(struct audio_device *dev, struct avdtp *session,
    575 				struct avdtp_stream *stream)
    576 {
    577 	struct source *source = dev->source;
    578 
    579 	if (source->stream)
    580 		return FALSE;
    581 
    582 	if (!source->session)
    583 		source->session = avdtp_ref(session);
    584 
    585 	source->stream = stream;
    586 
    587 	source->cb_id = avdtp_stream_add_cb(session, stream,
    588 						stream_state_changed, dev);
    589 
    590 	return TRUE;
    591 }
    592 
    593 gboolean source_shutdown(struct source *source)
    594 {
    595 	if (!source->stream)
    596 		return FALSE;
    597 
    598 	if (avdtp_close(source->session, source->stream, FALSE) < 0)
    599 		return FALSE;
    600 
    601 	return TRUE;
    602 }
    603 
    604 unsigned int source_add_state_cb(source_state_cb cb, void *user_data)
    605 {
    606 	struct source_state_callback *state_cb;
    607 	static unsigned int id = 0;
    608 
    609 	state_cb = g_new(struct source_state_callback, 1);
    610 	state_cb->cb = cb;
    611 	state_cb->user_data = user_data;
    612 	state_cb->id = ++id;
    613 
    614 	source_callbacks = g_slist_append(source_callbacks, state_cb);
    615 
    616 	return state_cb->id;
    617 }
    618 
    619 gboolean source_remove_state_cb(unsigned int id)
    620 {
    621 	GSList *l;
    622 
    623 	for (l = source_callbacks; l != NULL; l = l->next) {
    624 		struct source_state_callback *cb = l->data;
    625 		if (cb && cb->id == id) {
    626 			source_callbacks = g_slist_remove(source_callbacks, cb);
    627 			g_free(cb);
    628 			return TRUE;
    629 		}
    630 	}
    631 
    632 	return FALSE;
    633 }
    634