a2dp.c revision 847dad179fe16ec395373e4b55d46dcd400c623a
1e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg/*
2e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
3e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  BlueZ - Bluetooth protocol stack for Linux
4e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
5e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
6e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
7e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
8e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  This program is free software; you can redistribute it and/or modify
9e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  it under the terms of the GNU General Public License as published by
10e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  the Free Software Foundation; either version 2 of the License, or
11e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  (at your option) any later version.
12e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
13e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  This program is distributed in the hope that it will be useful,
14e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  GNU General Public License for more details.
17e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
18e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  You should have received a copy of the GNU General Public License
19e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  along with this program; if not, write to the Free Software
20e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg *
22e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg */
23e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg
24e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#ifdef HAVE_CONFIG_H
25e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#include <config.h>
26e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#endif
27e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg
286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <stdlib.h>
29847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg#include <errno.h>
306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <dbus/dbus.h>
326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <glib.h>
336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
34c2833e263d6cfc4cf82f4bfdcc59640a4071aeaeJohan Hedberg#include <bluetooth/bluetooth.h>
356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <bluetooth/sdp.h>
366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <bluetooth/sdp_lib.h>
376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "logging.h"
39d013a1eaa7beebbb49c1fe0015c70ad81566d97cJohan Hedberg#include "device.h"
40296dcf42cf8a4f4d6f0192cac58a28887be38552Johan Hedberg#include "manager.h"
416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "avdtp.h"
42f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg#include "sink.h"
43e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#include "a2dp.h"
446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
45c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz#define MAX_BITPOOL 64
46c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz#define MIN_BITPOOL 2
47c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz
48c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg/* The duration that streams without users are allowed to stay in
49c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg * STREAMING state. */
50c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg#define SUSPEND_TIMEOUT 5000
51c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
52cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MIN
53cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MIN(x, y) ((x) < (y) ? (x) : (y))
54cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
55cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
56cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MAX
57cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MAX(x, y) ((x) > (y) ? (x) : (y))
58cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
59cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
60cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_sep {
61666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	uint8_t type;
62cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_local_sep *sep;
63c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	struct avdtp *session;
64cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
65c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	guint suspend_timer;
66666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	gboolean locked;
67cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean suspending;
68cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean starting;
69cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
70cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
71cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_cb {
72cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	a2dp_stream_cb_t cb;
73cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	void *user_data;
74cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	int id;
75cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
76cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
77cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_setup {
78cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp *session;
79828133c3180a090a06ace6637d9f84ae5f57ae33Johan Hedberg	struct a2dp_sep *sep;
80cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	struct avdtp_service_capability *media_codec;
82cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean start;
83cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean canceled;
84cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *cb;
85cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
86cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic DBusConnection *connection = NULL;
886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
89666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic GSList *sinks = NULL;
90666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic GSList *sources = NULL;
91666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
92666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic uint32_t source_record_id = 0;
93666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic uint32_t sink_record_id = 0;
946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9503490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedbergstatic GSList *setups = NULL;
966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
97cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void stream_setup_free(struct a2dp_stream_setup *s)
98cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
9903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setups = g_slist_remove(setups, s);
100cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (s->session)
101cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_unref(s->session);
102cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_foreach(s->cb, (GFunc) g_free, NULL);
103cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_free(s->cb);
104cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_free(s);
105cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
106cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
107fc0d501d82773718d0f2d040f786136332c39813Johan Hedbergstatic struct device *a2dp_get_dev(struct avdtp *session)
108fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg{
109fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	bdaddr_t addr;
110fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg
111fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	avdtp_get_peers(session, NULL, &addr);
112fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg
113fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	return manager_device_connected(&addr, A2DP_SOURCE_UUID);
114fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg}
115fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg
116847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedbergstatic gboolean finalize_stream_setup(struct a2dp_stream_setup *s, struct avdtp_error *err)
117cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
118847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	GSList *l;
119847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg
120847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	for (l = s->cb; l != NULL; l = l->next) {
121847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		struct a2dp_stream_cb *cb = l->data;
122847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg
123847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		cb->cb(s->session, s->sep, s->stream, cb->user_data, err);
124847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	}
125cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
12603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	stream_setup_free(s);
12778a94059160d7478624cad315022255f7ebbbe80Johan Hedberg	return FALSE;
128cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1291addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
130847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedbergstatic gboolean finalize_stream_setup_errno(struct a2dp_stream_setup *s, int err)
131847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg{
132847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	struct avdtp_error avdtp_err;
133847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg
134847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	avdtp_error_init(&avdtp_err, AVDTP_ERROR_ERRNO, -err);
135847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg
136847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	return finalize_stream_setup(s, err ? &avdtp_err : NULL);
137847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg}
138847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg
13903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedbergstatic struct a2dp_stream_setup *find_setup_by_session(struct avdtp *session)
14003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg{
14103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	GSList *l;
14203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
14303490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	for (l = setups; l != NULL; l = l->next) {
14403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		struct a2dp_stream_setup *setup = l->data;
14503490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
14603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		if (setup->session == session)
14703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg			return setup;
14803490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	}
14903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
15003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	return NULL;
15103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg}
15203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
15303490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedbergstatic struct a2dp_stream_setup *find_setup_by_dev(struct device *dev)
15403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg{
15503490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	GSList *l;
15603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
15703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	for (l = setups; l != NULL; l = l->next) {
15803490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		struct a2dp_stream_setup *setup = l->data;
159fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		struct device *setup_dev = a2dp_get_dev(setup->session);
16003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
161fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		if (setup_dev == dev)
16203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg			return setup;
16303490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	}
16403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
16503490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	return NULL;
16603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg}
16703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
1687a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedbergstatic void stream_state_changed(struct avdtp_stream *stream,
1697a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					avdtp_state_t old_state,
1707a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					avdtp_state_t new_state,
1717a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					struct avdtp_error *err,
1727a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					void *user_data)
1737a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg{
1747a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	struct a2dp_sep *sep = user_data;
1757a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1767a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (new_state != AVDTP_STATE_IDLE)
1777a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		return;
1787a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1797a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (sep->suspend_timer) {
1807a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		g_source_remove(sep->suspend_timer);
1817a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		sep->suspend_timer = 0;
1827a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	}
1837a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1847a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (sep->session) {
1857a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		avdtp_unref(sep->session);
1867a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		sep->session = NULL;
1877a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	}
1887a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1897a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	sep->stream = NULL;
1907a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg}
1917a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
1935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	switch (freq) {
1955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	case A2DP_SAMPLING_FREQ_16000:
1965402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	case A2DP_SAMPLING_FREQ_32000:
1975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return 53;
1985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	case A2DP_SAMPLING_FREQ_44100:
1995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		switch (mode) {
2005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_MONO:
2015402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
2025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 31;
2035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_STEREO:
2045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_JOINT_STEREO:
2055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 53;
2065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		default:
2075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			error("Invalid channel mode %u", mode);
2085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 53;
2095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
2105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	case A2DP_SAMPLING_FREQ_48000:
2115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		switch (mode) {
2125402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_MONO:
2135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
2145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 29;
2155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_STEREO:
2165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		case A2DP_CHANNEL_MODE_JOINT_STEREO:
2175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 51;
2185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		default:
2195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			error("Invalid channel mode %u", mode);
2205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return 51;
2215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
2225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	default:
2235402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("Invalid sampling freq %u", freq);
2245402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return 53;
2255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
2265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
2275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentzstatic gboolean select_sbc_params(struct sbc_codec_cap *cap,
2295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz					struct sbc_codec_cap *supported)
2305402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
2315402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	uint max_bitpool, min_bitpool;
2325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	memset(cap, 0, sizeof(struct sbc_codec_cap));
2345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
2365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	cap->cap.media_codec_type = A2DP_CODEC_SBC;
2375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
238734b3f84c1e48f241bf1004e57a86fa898d083a5Marcel Holtmann	if (supported->frequency & A2DP_SAMPLING_FREQ_44100)
2395402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->frequency = A2DP_SAMPLING_FREQ_44100;
240734b3f84c1e48f241bf1004e57a86fa898d083a5Marcel Holtmann	else if (supported->frequency & A2DP_SAMPLING_FREQ_48000)
241734b3f84c1e48f241bf1004e57a86fa898d083a5Marcel Holtmann		cap->frequency = A2DP_SAMPLING_FREQ_48000;
2425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->frequency & A2DP_SAMPLING_FREQ_32000)
2435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->frequency = A2DP_SAMPLING_FREQ_32000;
2445402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->frequency & A2DP_SAMPLING_FREQ_16000)
2455402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->frequency = A2DP_SAMPLING_FREQ_16000;
2465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else {
2475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("No supported frequencies");
2485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return FALSE;
2495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
2505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (supported->channel_mode & A2DP_CHANNEL_MODE_JOINT_STEREO)
2525402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
2535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->channel_mode & A2DP_CHANNEL_MODE_STEREO)
2545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;
2555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->channel_mode & A2DP_CHANNEL_MODE_DUAL_CHANNEL)
2565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;
2575402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->channel_mode & A2DP_CHANNEL_MODE_MONO)
2585402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->channel_mode = A2DP_CHANNEL_MODE_MONO;
2595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else {
2605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("No supported channel modes");
2615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return FALSE;
2625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
2635402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (supported->block_length & A2DP_BLOCK_LENGTH_16)
2655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->block_length = A2DP_BLOCK_LENGTH_16;
2665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->block_length & A2DP_BLOCK_LENGTH_12)
2675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->block_length = A2DP_BLOCK_LENGTH_12;
2685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->block_length & A2DP_BLOCK_LENGTH_8)
2695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->block_length = A2DP_BLOCK_LENGTH_8;
2705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->block_length & A2DP_BLOCK_LENGTH_4)
2715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->block_length = A2DP_BLOCK_LENGTH_4;
2725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else {
2735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("No supported block lengths");
2745402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return FALSE;
2755402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
2765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (supported->subbands & A2DP_SUBBANDS_8)
2785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->subbands = A2DP_SUBBANDS_8;
2795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->subbands & A2DP_SUBBANDS_4)
2805402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->subbands = A2DP_SUBBANDS_4;
2815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else {
2825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("No supported subbands");
2835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return FALSE;
2845402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
2855402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2865402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (supported->allocation_method & A2DP_ALLOCATION_LOUDNESS)
2875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
2885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	else if (supported->allocation_method & A2DP_ALLOCATION_SNR)
2895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		cap->allocation_method = A2DP_ALLOCATION_SNR;
2905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
291c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	min_bitpool = MAX(MIN_BITPOOL, supported->min_bitpool);
2925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
2934183300934043b1038c84652848c271a235bc5dfMarcel Holtmann							supported->max_bitpool);
2945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
2965402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
2975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
2985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return TRUE;
2995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
3005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
30103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedbergstatic gboolean a2dp_select_capabilities(struct avdtp *session,
30203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg						struct avdtp_remote_sep *rsep,
3035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz						GSList **caps)
3045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
3055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	struct avdtp_service_capability *media_transport, *media_codec;
30669e07f5a7b3934fac5bcf4c554e14e0d0b3cec47Luiz Augusto von Dentz	struct sbc_codec_cap sbc_cap;
30703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
3085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
30903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
3105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (!setup)
3115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return FALSE;
3125402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3134183300934043b1038c84652848c271a235bc5dfMarcel Holtmann	if (setup->media_codec) {
31469e07f5a7b3934fac5bcf4c554e14e0d0b3cec47Luiz Augusto von Dentz		memcpy(&sbc_cap, setup->media_codec->data, sizeof(sbc_cap));
3154183300934043b1038c84652848c271a235bc5dfMarcel Holtmann	} else {
3165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		media_codec = avdtp_get_codec(rsep);
3175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (!media_codec)
3185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return FALSE;
3195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		select_sbc_params(&sbc_cap,
32141b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz			(struct sbc_codec_cap *) media_codec->data);
3225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
3235402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3245402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
3255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz						NULL, 0);
3265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	*caps = g_slist_append(*caps, media_transport);
3285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
3305402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz						sizeof(sbc_cap));
3315402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	*caps = g_slist_append(*caps, media_codec);
3335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
33469e07f5a7b3934fac5bcf4c554e14e0d0b3cec47Luiz Augusto von Dentz
3355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return TRUE;
3365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
3375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
338847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedbergstatic void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err,
3395402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				void *user_data)
3405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
3415402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	struct avdtp_local_sep *lsep;
3425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	struct avdtp_remote_sep *rsep;
34303490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
3445402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	GSList *caps = NULL;
345847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	int posix_err;
3465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
34703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
34803490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
34903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	if (!setup)
35003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		return;
35103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
352847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	if (err || setup->canceled) {
3535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		setup->stream = NULL;
354847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
3555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
3565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
3575402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3585402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	debug("Discovery complete");
3595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
3605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
3615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				A2DP_CODEC_SBC, &lsep, &rsep) < 0) {
3625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("No matching ACP and INT SEPs found");
363847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup_errno(setup, -EINVAL);
3645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
3655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
3665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
36703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	if (!a2dp_select_capabilities(session, rsep, &caps)) {
3685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("Unable to select remote SEP capabilities");
369847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup_errno(setup, -EINVAL);
3705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
3715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
3725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
373847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	posix_err = avdtp_set_configuration(session, rsep, lsep, caps,
3744183300934043b1038c84652848c271a235bc5dfMarcel Holtmann							&setup->stream);
375847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	if (posix_err < 0) {
376847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		error("avdtp_set_configuration: %s", strerror(-posix_err));
377847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup_errno(setup, posix_err);
3785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
3795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
3805402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
381f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedbergstatic gboolean setconf_ind(struct avdtp *session,
382f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				struct avdtp_local_sep *sep,
3836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream,
384f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				GSList *caps, uint8_t *err,
385666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *category, void *user_data)
3866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
387666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
388f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	struct device *dev;
389c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	struct avdtp_service_capability *cap;
390c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	struct avdtp_media_codec_capability *codec_cap;
391c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	struct sbc_codec_cap *sbc_cap;
392f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
393666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
3946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Ind");
395666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
396c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Set_Configuration_Ind");
397f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
398fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	dev = a2dp_get_dev(session);
399f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	if (!dev) {
400f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
401f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*category = 0x00;
402f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		return FALSE;
403f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	}
404f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
405c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	/* Check bipool range */
406c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	for (codec_cap = NULL; caps; caps = g_slist_next(caps)) {
407c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz		cap = caps->data;
408c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz		if (cap->category == AVDTP_MEDIA_CODEC) {
409c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz			codec_cap = (void *) cap->data;
410c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz			if (codec_cap->media_codec_type == A2DP_CODEC_SBC) {
411c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz				sbc_cap = (void *) codec_cap;
412c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz				if (sbc_cap->min_bitpool < MIN_BITPOOL ||
413c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz					sbc_cap->max_bitpool > MAX_BITPOOL) {
414c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz					*err = AVDTP_UNSUPPORTED_CONFIGURATION;
415c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz					*category = AVDTP_MEDIA_CODEC;
416c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz					return FALSE;
417c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz				}
418c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz			}
419c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz			break;
420c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz		}
421c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	}
422c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz
4237a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
424c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->stream = stream;
425cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
426666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
427c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		sink_new_stream(dev, session, stream);
4286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
432f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep,
433666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				GSList **caps, uint8_t *err, void *user_data)
4346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
435666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
4366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *media_transport, *media_codec;
4376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap sbc_cap;
4386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
439666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Capability_Ind");
4416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
4426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Capability_Ind");
4436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = NULL;
4456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
4476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						NULL, 0);
4486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_transport);
4506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&sbc_cap, 0, sizeof(struct sbc_codec_cap));
4526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
4546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
4556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.frequency = ( A2DP_SAMPLING_FREQ_48000 |
4576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_44100 |
4586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_32000 |
4596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_16000 );
4606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.channel_mode = ( A2DP_CHANNEL_MODE_JOINT_STEREO |
4626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_STEREO |
4636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_DUAL_CHANNEL |
4646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_MONO );
4656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.block_length = ( A2DP_BLOCK_LENGTH_16 |
4676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_12 |
4686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_8 |
4696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_4 );
4706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.subbands = ( A2DP_SUBBANDS_8 | A2DP_SUBBANDS_4 );
4726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.allocation_method = ( A2DP_ALLOCATION_LOUDNESS |
4746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_ALLOCATION_SNR );
4756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
476c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	sbc_cap.min_bitpool = MIN_BITPOOL;
477c4be6b437310018f154f7a01e6a3ddc2c9d1e175Luiz Augusto von Dentz	sbc_cap.max_bitpool = MAX_BITPOOL;
4786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
4806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sizeof(sbc_cap));
4816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_codec);
4836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
487f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
4880f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg				struct avdtp_stream *stream,
489666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_error *err, void *user_data)
4906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
491666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
49203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
493fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	struct device *dev;
4940f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	int ret;
495cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
496666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
498666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
499c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Set_Configuration_Cfm");
500cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
50103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
50203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
5030f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
5040f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (setup)
505847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg			finalize_stream_setup(setup, err);
5060f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		return;
5070f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
5080f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
5097a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
510c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->stream = stream;
511cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
512cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
513cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
514cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
515fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	dev = a2dp_get_dev(session);
516fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg
51767d1e1774b3ff2d7a09fcf49484515bd85c02d14Johan Hedberg	/* Notify sink.c of the new stream */
518fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	sink_new_stream(dev, session, setup->stream);
51967d1e1774b3ff2d7a09fcf49484515bd85c02d14Johan Hedberg
5200f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	ret = avdtp_open(session, stream);
5210f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (ret < 0) {
5220f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		error("Error on avdtp_open %s (%d)", strerror(-ret),
5230f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg				-ret);
5247a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		setup->stream = NULL;
525847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup_errno(setup, ret);
526cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
5276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
529f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
530666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *err, void *user_data)
5316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
532666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
533666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
534666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
5356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Configuration_Ind");
5366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Configuration_Ind");
5386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
5396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
541f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
542666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
543666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
5446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
545666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
546666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
547666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
5486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
5496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Set_Configuration_Cfm");
5516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
553f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
554666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
555666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
5566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
557666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
558666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
559666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
5606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Ind");
5616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Ind");
5636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
5646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
566f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
567666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
568666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
5696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
570666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
57103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
572847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	int posix_err;
573666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
574666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
5756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Cfm");
5766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Cfm");
5781addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
57903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
580cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
5811addff77624b54445c9b81779ddc78892a126a45Johan Hedberg		return;
5821addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
583cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
5840f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (!err)
5850f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			avdtp_close(session, stream);
586cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
587cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
588cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
589cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
5900f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
5910f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		setup->stream = NULL;
592847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
593847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		return;
5940f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
5950f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
596cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->start) {
597847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = avdtp_start(session, stream);
598847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		if (posix_err == 0)
599cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			return;
6001addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
601cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("avdtp_start failed");
602847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		setup->stream = NULL;
6035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
604847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	else
605847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = 0;
606cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
607847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	finalize_stream_setup_errno(setup, -posix_err);
6086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
610c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedbergstatic gboolean suspend_timeout(struct a2dp_sep *sep)
611c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg{
612c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	if (avdtp_suspend(sep->session, sep->stream) == 0)
613c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		sep->suspending = TRUE;
614c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
6157a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	sep->suspend_timer = 0;
616c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
617c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	avdtp_unref(sep->session);
618c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	sep->session = NULL;
619c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
620c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	return FALSE;
621c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg}
622c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
623f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep,
624666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
625666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
6266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
627666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
628c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
629666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
6306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Ind");
631666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
6326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Ind");
6335b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg
634c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->session = avdtp_ref(session);
635c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
636c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->suspend_timer = g_timeout_add(SUSPEND_TIMEOUT,
637c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg						(GSourceFunc) suspend_timeout,
638c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg						a2dp_sep);
639c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	return TRUE;
6406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
642f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
643666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
644666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
6456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
646666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
64703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
648666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
649666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
6506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Cfm");
6516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
6526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Cfm");
653cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
65403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
655cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
656cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
657cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
658cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
6590f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (!err)
6600f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			avdtp_close(session, stream);
661cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
662cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
663cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
664cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
665847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	if (err) {
6660f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		setup->stream = NULL;
667847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
668847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	}
669847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	else
670847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup_errno(setup, 0);
6716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
673f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
674666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
675666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
6766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
677666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
678666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
679666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
6806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Ind");
6816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
6826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Suspend_Ind");
6836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
6846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
686f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
687666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
688666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
6896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
690666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
69103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
692847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	int posix_err;
693c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
694666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
6956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Cfm");
696666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
697c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Suspend_Cfm");
698cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
699c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->suspending = FALSE;
700cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
70103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
70203490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	if (!setup)
70303490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		return;
70403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
7050f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
706847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
7070f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		return;
7080f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
7090f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
71003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	if (setup->start) {
711847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = avdtp_start(session, stream);
712847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		if (posix_err < 0)
713847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg			finalize_stream_setup_errno(setup, posix_err);
714cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
7156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
717f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
718666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
719666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
7206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
721666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
722c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
723666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
7246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Ind");
725666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
726c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Close_Ind");
727cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
7286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
7296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
731f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
732666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
733666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
7346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
735666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
73603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
737847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	int posix_err;
738c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
739666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
7406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Cfm");
741666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
742c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Close_Cfm");
7435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
74403490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
7455402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (!setup)
7465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
7475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
7485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (setup->canceled) {
7495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		stream_setup_free(setup);
7505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
7515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
7525402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
7535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (err) {
7545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		setup->stream = NULL;
755847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
756847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		return;
7575402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
7585402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
7595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (setup->start) {
760847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = avdtp_discover(session, discovery_complete, setup);
761847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		if (posix_err == 0)
7625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return;
7635402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
7645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("avdtp_discover failed");
7655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		setup->stream = NULL;
7665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
767847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	else
768847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = 0;
7695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
770847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	finalize_stream_setup_errno(setup, -posix_err);
7716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
773f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
774666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
775666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
777666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
778c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
779666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
7806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Ind");
781666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
782c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Abort_Ind");
783cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
784fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	a2dp_sep->stream = NULL;
78503490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
7866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
7876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
789f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
790666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
791666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
7926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
793666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
794c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
795666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
7966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Cfm");
797666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
7986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Abort_Cfm");
7996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
801f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
802666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *err, void *user_data)
8036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
804666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
805666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
806666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
8076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Ind");
8086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
8096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Ind");
8106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
8116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8130f458da19471c933a4105cc450c48548b72edc8eJohan Hedbergstatic void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
814666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
815666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
8166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
817666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
81803490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
819847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	int posix_err;
820666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
821666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
8226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Cfm");
8236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
8246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Cfm");
8255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
82603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
8275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (!setup)
8285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
8295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
8305402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (setup->canceled) {
8315402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (!err)
8325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			avdtp_close(session, stream);
8335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		stream_setup_free(setup);
8345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		return;
8355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
8365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
8375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (err) {
8385402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		setup->stream = NULL;
839847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		finalize_stream_setup(setup, err);
840847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		return;
8415402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
8425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
8435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	if (setup->start) {
844847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = avdtp_start(session, stream);
845847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		if (posix_err == 0)
8465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			return;
8475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
8485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		error("avdtp_start failed");
8495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		setup->stream = NULL;
8505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	}
851847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	else
852847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg		posix_err = 0;
8535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
854847dad179fe16ec395373e4b55d46dcd400c623aJohan Hedberg	finalize_stream_setup_errno(setup, -posix_err);
8556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_cfm cfm = {
8586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_cfm,
8596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_cfm,
8606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_cfm,
8616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_cfm,
8626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_cfm,
8636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_cfm,
8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_cfm,
8656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_cfm
8666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
8676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_ind ind = {
8696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_capability		= getcap_ind,
8706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_ind,
8716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_ind,
8726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_ind,
8736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_ind,
8746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_ind,
8756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_ind,
8766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_ind,
8776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_ind
8786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
8796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_source_record(sdp_buf_t *buf)
8816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
8826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
8836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uuid_t root_uuid, l2cap, avdtp, a2src;
8846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_profile_desc_t profile[1];
8856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *aproto, *proto[2];
8866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_record_t record;
8876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_data_t *psm, *version, *features;
8886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t lp = AVDTP_UUID, ver = 0x0100, feat = 0x000F;
8896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int ret = 0;
8906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&record, 0, sizeof(sdp_record_t));
8926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
8946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	root = sdp_list_append(0, &root_uuid);
8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_browse_groups(&record, root);
8966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	svclass_id = sdp_list_append(0, &a2src);
8996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_service_classes(&record, svclass_id);
9006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
9026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	profile[0].version = 0x0100;
9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	pfseq = sdp_list_append(0, &profile[0]);
9046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_profile_descs(&record, pfseq);
9056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&l2cap, L2CAP_UUID);
9076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(0, &l2cap);
9086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	psm = sdp_data_alloc(SDP_UINT16, &lp);
9096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(proto[0], psm);
9106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(0, proto[0]);
9116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&avdtp, AVDTP_UUID);
9136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(0, &avdtp);
9146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	version = sdp_data_alloc(SDP_UINT16, &ver);
9156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(proto[1], version);
9166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(apseq, proto[1]);
9176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	aproto = sdp_list_append(0, apseq);
9196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_access_protos(&record, aproto);
9206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	features = sdp_data_alloc(SDP_UINT16, &feat);
9226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
9236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_info_attr(&record, "Audio Source", 0, 0);
9256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (sdp_gen_record_pdu(&record, buf) < 0)
9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = -1;
9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = 0;
9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(psm);
9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(version);
9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[0], 0);
9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[1], 0);
9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(apseq, 0);
9366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(pfseq, 0);
9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(aproto, 0);
9386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(root, 0);
9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(svclass_id, 0);
9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);
9416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.pattern, free);
9426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_sink_record(sdp_buf_t *buf)
9476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
9496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
951666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type)
9526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
953666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep;
954666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList **l;
955666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	int (*create_record)(sdp_buf_t *buf);
956666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	uint32_t *record_id;
9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_buf_t buf;
9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
959666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep = g_new0(struct a2dp_sep, 1);
960666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
961666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO,
962666938b54d631956826343ed278e2af4b982fc29Johan Hedberg					&ind, &cfm, sep);
963666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (sep->sep == NULL) {
964666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
965666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
966666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
967666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
968666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->type = type;
969666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
970666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (type == AVDTP_SEP_TYPE_SOURCE) {
971666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		l = &sources;
972666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		create_record = a2dp_source_record;
973666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		record_id = &source_record_id;
974666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	} else {
975666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		l = &sinks;
976666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		create_record = a2dp_sink_record;
977666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		record_id = &sink_record_id;
978666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
979666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
980666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (*record_id != 0)
981666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		goto add;
982666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
983666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (create_record(&buf) < 0) {
984666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("Unable to allocate new service record");
985666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		avdtp_unregister_sep(sep->sep);
986666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
987666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
988666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
989666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
990666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	*record_id = add_service_record(conn, &buf);
991666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	free(buf.data);
992666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!*record_id) {
993666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("Unable to register A2DP service record");
994666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		avdtp_unregister_sep(sep->sep);
995666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
996666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
997666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
998666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
999666938b54d631956826343ed278e2af4b982fc29Johan Hedbergadd:
1000666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	*l = g_slist_append(*l, sep);
1001666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1002666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	return sep;
1003666938b54d631956826343ed278e2af4b982fc29Johan Hedberg}
1004666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1005e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedbergint a2dp_init(DBusConnection *conn, int sources, int sinks)
1006666938b54d631956826343ed278e2af4b982fc29Johan Hedberg{
1007e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedberg	int i;
1008e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedberg
1009e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedberg	if (!sources && !sinks)
10106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 0;
10116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	connection = dbus_connection_ref(conn);
10136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	avdtp_init();
10156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1016e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedberg	for (i = 0; i < sources; i++)
1017666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE);
10186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1019e2827b35575bab20a99a170805a0a59a32fb2c48Johan Hedberg	for (i = 0; i < sinks; i++)
1020666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK);
10216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
10236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
10246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1025666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic void a2dp_unregister_sep(struct a2dp_sep *sep)
1026666938b54d631956826343ed278e2af4b982fc29Johan Hedberg{
1027666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	avdtp_unregister_sep(sep->sep);
1028666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_free(sep);
1029666938b54d631956826343ed278e2af4b982fc29Johan Hedberg}
1030666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
10316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergvoid a2dp_exit()
10326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
1033666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_foreach(sinks, (GFunc) a2dp_unregister_sep, NULL);
1034666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_free(sinks);
1035666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sinks = NULL;
10366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1037666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_foreach(sources, (GFunc) a2dp_unregister_sep, NULL);
1038666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_free(sources);
1039666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sources = NULL;
10406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1041666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (source_record_id) {
1042666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		remove_service_record(connection, source_record_id);
1043666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		source_record_id = 0;
10446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
10456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1046666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (sink_record_id) {
1047666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		remove_service_record(connection, sink_record_id);
1048666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sink_record_id = 0;
10496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
10506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	dbus_connection_unref(connection);
10526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
10536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1054d1fb0b25a9882016de70f102408f10101b348e57Johan Hedberggboolean a2dp_source_cancel_stream(struct device *dev, unsigned int id)
1055cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1056cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
105703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
1058cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *l;
1059cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
106003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_dev(dev);
1061cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
1062cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1063cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1064cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	for (cb_data = NULL, l = setup->cb; l != NULL; l = g_slist_next(l)) {
1065cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		struct a2dp_stream_cb *cb = l->data;
1066cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1067cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (cb->id == id) {
1068cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			cb_data = cb;
1069cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
1070cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
1071cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1072cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1073cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!cb_data)
1074cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1075cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1076cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_remove(setup->cb, cb_data);
10779ce01693dd0aa7407b7d8eb37c8524dd05abe15cJohan Hedberg	g_free(cb_data);
1078cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1079828133c3180a090a06ace6637d9f84ae5f57ae33Johan Hedberg	if (!setup->cb) {
1080cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = TRUE;
108103490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		setup->sep = NULL;
1082828133c3180a090a06ace6637d9f84ae5f57ae33Johan Hedberg	}
1083cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1084cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
1085cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1086cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
10870f458da19471c933a4105cc450c48548b72edc8eJohan Hedbergunsigned int a2dp_source_request_stream(struct avdtp *session,
1088666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						gboolean start,
1089666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						a2dp_stream_cb_t cb,
1090666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						void *user_data,
10915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz						struct avdtp_service_capability *media_codec)
1092cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1093cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
1094cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	static unsigned int cb_id = 0;
1095666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
109603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	struct a2dp_stream_setup *setup;
1097666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1098cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1099666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1100666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1101666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1102666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->locked)
1103666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			continue;
1104666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1105fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		if (!tmp->stream || avdtp_has_stream(session, tmp->stream)) {
1106666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1107666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1108666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1109666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1110666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1111666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep) {
1112666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("a2dp_source_request_stream: no available SEP found");
1113730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		return 0;
1114730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg	}
1115730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
111603490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setup = find_setup_by_session(session);
1117730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
1118666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	debug("a2dp_source_request_stream: selected SEP %p", sep);
1119666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1120cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data = g_new(struct a2dp_stream_cb, 1);
1121cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->cb = cb;
1122cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->user_data = user_data;
11230f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	cb_data->id = ++cb_id;
1124cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1125cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup) {
1126cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = FALSE;
112703490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg		setup->sep = sep;
1128cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->cb = g_slist_append(setup->cb, cb_data);
1129cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (start)
1130cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			setup->start = TRUE;
1131cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return cb_data->id;
1132cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1133cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1134cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup = g_new0(struct a2dp_stream_setup, 1);
1135cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->session = avdtp_ref(session);
1136828133c3180a090a06ace6637d9f84ae5f57ae33Johan Hedberg	setup->sep = sep;
1137cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_append(setup->cb, cb_data);
1138cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->start = start;
1139666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	setup->stream = sep->stream;
11405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	setup->media_codec = media_codec;
1141cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1142666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	switch (avdtp_sep_get_state(sep->sep)) {
1143cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_IDLE:
1144730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		if (avdtp_discover(session, discovery_complete, setup) < 0) {
1145730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg			error("avdtp_discover failed");
1146cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
1147730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		}
1148cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1149cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
1150cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!start) {
1151cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
1152cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
1153cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
1154666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (sep->starting)
1155cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
11565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (setup->media_codec) {
11575402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (avdtp_stream_has_capability(setup->stream,
11584183300934043b1038c84652848c271a235bc5dfMarcel Holtmann							setup->media_codec)) {
11595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				if (avdtp_start(session, sep->stream) < 0) {
11605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz					error("avdtp_start failed");
11615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz					goto failed;
11625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				}
11635402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			} else {
11645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				if (avdtp_close(session, sep->stream) < 0) {
11655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz					error("avdtp_close failed");
11665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz					goto failed;
11675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				}
11685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
11695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
11705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		else if (avdtp_start(session, sep->stream) < 0) {
1171730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg			error("avdtp_start failed");
1172cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
1173730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		}
1174cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1175cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
1176666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (!start || !sep->suspending) {
1177666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			if (sep->suspend_timer) {
1178666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				g_source_remove(sep->suspend_timer);
1179666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				sep->suspend_timer = 0;
118058b173171f61373c7eb8ed00d0635fb06fa741ccJohan Hedberg			}
1181edce261bbbcaa3bca4d68289e4f244c1f709c0c9Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
1182cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
1183cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1184cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
1185730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		error("SEP in bad state for requesting a new stream");
1186cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		goto failed;
1187cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
11885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
118903490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg	setups = g_slist_append(setups, setup);
119003490d81bbe11641c47cd8e7e0c64a45db4f80f4Johan Hedberg
1191cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return cb_data->id;
1192cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1193cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergfailed:
1194cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	stream_setup_free(setup);
1195cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_id--;
11960f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	return 0;
1197cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1198cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1199fc0d501d82773718d0f2d040f786136332c39813Johan Hedberggboolean a2dp_sep_lock(struct a2dp_sep *sep, struct avdtp *session)
1200cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1201fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	if (sep->locked)
1202fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		return FALSE;
1203f4211a3cd3442d54fa7877a6c421bee034d46e8eJohan Hedberg
1204fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	debug("SBC Source SEP %p locked", sep);
1205fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	sep->locked = TRUE;
1206666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1207fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg	return TRUE;
1208cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1209cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1210fc0d501d82773718d0f2d040f786136332c39813Johan Hedberggboolean a2dp_sep_unlock(struct a2dp_sep *sep, struct avdtp *session)
1211cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1212cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1213cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1214666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1215cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1216666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->locked = FALSE;
1217cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1218666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	debug("SBC Source SEP %p unlocked", sep);
1219730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
1220666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep->stream || state == AVDTP_STATE_IDLE)
1221cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1222cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1223cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	switch (state) {
1224cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
1225cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		/* Set timer here */
1226cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1227cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
1228666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (avdtp_suspend(session, sep->stream) == 0)
1229666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep->suspending = TRUE;
1230cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1231cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
1232cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1233cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1234cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1235cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
1236cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1237cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1238cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_suspend(struct device *dev, struct avdtp *session)
1239cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1240cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1241666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1242666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1243cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1244666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1245666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1246cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1247fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		if (tmp->session && tmp->session == session) {
1248666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1249666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1250666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1251666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1252666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1253666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep)
1254cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1255cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1256666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1257cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1258666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep->stream || state != AVDTP_STATE_STREAMING)
1259cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1260cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1261666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (avdtp_suspend(session, sep->stream) == 0) {
1262666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sep->suspending = TRUE;
1263cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1264cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1265cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1266cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return FALSE;
1267cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1268cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1269cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_start_stream(struct device *dev, struct avdtp *session)
1270cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1271cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1272666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1273666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1274cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1275666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1276666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1277666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1278fc0d501d82773718d0f2d040f786136332c39813Johan Hedberg		if (tmp->session && tmp->session == session) {
1279666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1280666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1281666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1282666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1283cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1284666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep)
1285cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1286cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1287666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1288cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1289cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state < AVDTP_STATE_OPEN) {
1290cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("a2dp_source_start_stream: no stream open");
1291cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1292cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1293cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1294cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state == AVDTP_STATE_STREAMING)
1295cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1296cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1297666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (avdtp_start(session, sep->stream) < 0)
1298cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1299cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1300cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
13011addff77624b54445c9b81779ddc78892a126a45Johan Hedberg}
1302