a2dp.c revision cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7
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>
296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <dbus/dbus.h>
316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <glib.h>
326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
33c2833e263d6cfc4cf82f4bfdcc59640a4071aeaeJohan Hedberg#include <bluetooth/bluetooth.h>
346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <bluetooth/sdp.h>
356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <bluetooth/sdp_lib.h>
366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "logging.h"
386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "manager.h"
39c2833e263d6cfc4cf82f4bfdcc59640a4071aeaeJohan Hedberg#include "ipc.h"
40d013a1eaa7beebbb49c1fe0015c70ad81566d97cJohan Hedberg#include "device.h"
416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "avdtp.h"
42f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg#include "sink.h"
43e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#include "a2dp.h"
446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
45cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MIN
46cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MIN(x, y) ((x) < (y) ? (x) : (y))
47cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
48cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
49cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MAX
50cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MAX(x, y) ((x) > (y) ? (x) : (y))
51cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
52cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
53cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_sep {
54cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_local_sep *sep;
55cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
56cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct device *used_by;
57cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	uint32_t record_id;
58cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean start_requested;
59cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean suspending;
60cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean starting;
61cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
62cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
63cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_cb {
64cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	a2dp_stream_cb_t cb;
65cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	void *user_data;
66cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	int id;
67cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
68cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
69cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_setup {
70cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp *session;
71cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct device *dev;
72cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
73cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean start;
74cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean canceled;
75cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *cb;
76cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
77cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic DBusConnection *connection = NULL;
796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
80cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic struct a2dp_sep sink = { NULL, NULL, 0 };
81cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic struct a2dp_sep source = { NULL, NULL, 0 };
826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
83cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic struct a2dp_stream_setup *setup = NULL;
846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
85cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void stream_setup_free(struct a2dp_stream_setup *s)
86cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
87cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (s->session)
88cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_unref(s->session);
89cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_foreach(s->cb, (GFunc) g_free, NULL);
90cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_free(s->cb);
91cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_free(s);
92cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup = NULL;
93cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
94cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
95cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void setup_callback(struct a2dp_stream_cb *cb,
96cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				struct a2dp_stream_setup *s)
97cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
98cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb->cb(s->session, s->dev, s->stream, cb->user_data);
99cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
100cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
101cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void finalize_stream_setup(struct a2dp_stream_setup *s)
102cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
103cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_foreach(setup->cb, (GFunc) setup_callback, setup);
104cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	stream_setup_free(setup);
105cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1061addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
107f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedbergstatic gboolean setconf_ind(struct avdtp *session,
108f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				struct avdtp_local_sep *sep,
1096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream,
110f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				GSList *caps, uint8_t *err,
111f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				uint8_t *category)
1126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
113f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	struct device *dev;
114f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	bdaddr_t addr;
115f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
116cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
1176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Ind");
118f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		return TRUE;
119f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	}
120f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
121f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	debug("SBC Source: Set_Configuration_Ind");
122f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
123f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	avdtp_get_peers(session, NULL, &addr);
124f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
125f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	dev = manager_device_connected(&addr, A2DP_SOURCE_UUID);
126f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	if (!dev) {
127f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
128f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*category = 0x00;
129f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		return FALSE;
130f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	}
131f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
132cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.stream = stream;
133cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
134d013a1eaa7beebbb49c1fe0015c70ad81566d97cJohan Hedberg	sink_new_stream(dev, session, stream);
1356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
1376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
1386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
139f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				GSList **caps, uint8_t *err)
1416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
1426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *media_transport, *media_codec;
1436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap sbc_cap;
1446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
145cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
1466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Capability_Ind");
1476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
1486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Capability_Ind");
1496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = NULL;
1516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
1536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						NULL, 0);
1546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_transport);
1566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&sbc_cap, 0, sizeof(struct sbc_codec_cap));
1586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
1606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
1616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.frequency = ( A2DP_SAMPLING_FREQ_48000 |
1636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_44100 |
1646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_32000 |
1656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_16000 );
1666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.channel_mode = ( A2DP_CHANNEL_MODE_JOINT_STEREO |
1686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_STEREO |
1696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_DUAL_CHANNEL |
1706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_MONO );
1716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.block_length = ( A2DP_BLOCK_LENGTH_16 |
1736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_12 |
1746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_8 |
1756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_4 );
1766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.subbands = ( A2DP_SUBBANDS_8 | A2DP_SUBBANDS_4 );
1786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.allocation_method = ( A2DP_ALLOCATION_LOUDNESS |
1806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_ALLOCATION_SNR );
1816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.min_bitpool = 2;
1836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.max_bitpool = 250;
1846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
1866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sizeof(sbc_cap));
1876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_codec);
1896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
1916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
1926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
193f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream)
1956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
196cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	int err;
197cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
198cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
1996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
200cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
201cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
202cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
203cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("SBC Source: Set_Configuration_Cfm");
204cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
205cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.stream = stream;
206cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
207cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
208cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
209cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
210cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	err = avdtp_open(session, stream);
211cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (err < 0) {
212cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("Error on avdtp_open %s (%d)", strerror(-err),
213cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				-err);
214cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->stream = FALSE;
215cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
216cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
2176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
219f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
220f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg				uint8_t *err)
2216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
222cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Configuration_Ind");
2246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Configuration_Ind");
2266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
2276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
229f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
2306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			struct avdtp_stream *stream)
2316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
232cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
2346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Set_Configuration_Cfm");
2366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
238f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
2396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream, uint8_t *err)
2406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
241cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Ind");
2436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Ind");
2456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
2466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
248f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
249f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg			struct avdtp_stream *stream)
2506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
251cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Cfm");
2536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Cfm");
2551addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
256cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
2571addff77624b54445c9b81779ddc78892a126a45Johan Hedberg		return;
2581addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
259cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
260cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_close(session, stream);
261cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
262cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
263cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
264cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
265cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->start) {
266cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (avdtp_start(session, stream) == 0)
267cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			return;
2681addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
269cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("avdtp_start failed");
270cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->stream = NULL;
271cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
272cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
273cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	finalize_stream_setup(setup);
2746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
276f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep,
2776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream, uint8_t *err)
2786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
279cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Ind");
2816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Ind");
2835b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg
2845b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg	/* Refuse to go into streaming state since this action should only be
2855b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg	 * initiated by alsa */
2865b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg	*err = AVDTP_NOT_SUPPORTED_COMMAND;
2875b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg	return FALSE;
2886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
290f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
291f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg			struct avdtp_stream *stream)
2926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
293cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
2946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Cfm");
2956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Cfm");
297cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
298cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
299cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
300cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
301cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
302cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_close(session, stream);
303cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
304cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
305cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
306cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
307cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	finalize_stream_setup(setup);
3086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
310f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
3116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream, uint8_t *err)
3126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
313cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
3146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Ind");
3156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
3166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Suspend_Ind");
3176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
3186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
320f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
3216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream)
3226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
323cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
3246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Cfm");
325cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
326cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
327cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
328cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("SBC Source: Suspend_Cfm");
329cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
330cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.suspending = FALSE;
331cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
332cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.start_requested) {
333cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_start(session, stream);
334cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.start_requested = FALSE;
335cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
3366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
338f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
3396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream, uint8_t *err)
3406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
341cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
3426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Ind");
343cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
344cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
345cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
346cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("SBC Source: Close_Ind");
347cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
348cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.stream = NULL;
349cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
3506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
3516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
353f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
354f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg			struct avdtp_stream *stream)
3556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
356cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
3576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Cfm");
358cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
359cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
360cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
361cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("SBC Source: Close_Cfm");
362cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
363cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.stream = NULL;
3646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
366f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
3676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream, uint8_t *err)
3686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
369cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep) {
3706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Ind");
371cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
372cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
373cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
374cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("SBC Source: Abort_Ind");
375cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
376cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.stream = NULL;
377cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
3786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
3796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
381f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
382f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg			struct avdtp_stream *stream)
3836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
384cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
3856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Cfm");
3866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
3876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Abort_Cfm");
3886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
390f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
391f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedberg				uint8_t *err)
3926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
393cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
3946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Ind");
3956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
3966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Ind");
3976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
3986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
400f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep)
4016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
402cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sep == sink.sep)
4036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Cfm");
4046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
4056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Cfm");
4066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_cfm cfm = {
4096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_cfm,
4106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_cfm,
4116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_cfm,
4126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_cfm,
4136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_cfm,
4146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_cfm,
4156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_cfm,
4166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_cfm
4176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
4186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_ind ind = {
4206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_capability		= getcap_ind,
4216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_ind,
4226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_ind,
4236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_ind,
4246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_ind,
4256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_ind,
4266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_ind,
4276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_ind,
4286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_ind
4296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
4306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_source_record(sdp_buf_t *buf)
4326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
4336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
4346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uuid_t root_uuid, l2cap, avdtp, a2src;
4356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_profile_desc_t profile[1];
4366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *aproto, *proto[2];
4376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_record_t record;
4386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_data_t *psm, *version, *features;
4396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t lp = AVDTP_UUID, ver = 0x0100, feat = 0x000F;
4406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int ret = 0;
4416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&record, 0, sizeof(sdp_record_t));
4436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
4456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	root = sdp_list_append(0, &root_uuid);
4466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_browse_groups(&record, root);
4476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
4496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	svclass_id = sdp_list_append(0, &a2src);
4506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_service_classes(&record, svclass_id);
4516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
4536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	profile[0].version = 0x0100;
4546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	pfseq = sdp_list_append(0, &profile[0]);
4556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_profile_descs(&record, pfseq);
4566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&l2cap, L2CAP_UUID);
4586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(0, &l2cap);
4596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	psm = sdp_data_alloc(SDP_UINT16, &lp);
4606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(proto[0], psm);
4616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(0, proto[0]);
4626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&avdtp, AVDTP_UUID);
4646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(0, &avdtp);
4656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	version = sdp_data_alloc(SDP_UINT16, &ver);
4666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(proto[1], version);
4676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(apseq, proto[1]);
4686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	aproto = sdp_list_append(0, apseq);
4706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_access_protos(&record, aproto);
4716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	features = sdp_data_alloc(SDP_UINT16, &feat);
4736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
4746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_info_attr(&record, "Audio Source", 0, 0);
4766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (sdp_gen_record_pdu(&record, buf) < 0)
4786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = -1;
4796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
4806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = 0;
4816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(psm);
4836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(version);
4846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[0], 0);
4856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[1], 0);
4866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(apseq, 0);
4876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(pfseq, 0);
4886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(aproto, 0);
4896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(root, 0);
4906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(svclass_id, 0);
4916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);
4926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.pattern, free);
4936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
4956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_sink_record(sdp_buf_t *buf)
4986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
4996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
5006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergint a2dp_init(DBusConnection *conn, gboolean enable_sink, gboolean enable_source)
5036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
5046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_buf_t buf;
5056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (!enable_sink && !enable_source)
5076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 0;
5086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	connection = dbus_connection_ref(conn);
5106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	avdtp_init();
5126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (enable_sink) {
514cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE,
515cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg							AVDTP_MEDIA_TYPE_AUDIO,
516cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg							&ind, &cfm);
517cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (source.sep == NULL)
5186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if (a2dp_source_record(&buf) < 0) {
5216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Unable to allocate new service record");
5226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
5246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
525cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.record_id = add_service_record(conn, &buf);
5266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		free(buf.data);
527cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!source.record_id) {
5286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Unable to register A2DP Source service record");
5296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
5316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (enable_source) {
534cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		sink.sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK,
5356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						AVDTP_MEDIA_TYPE_AUDIO,
5366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						&ind, &cfm);
537cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (sink.sep == NULL)
5386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if (a2dp_sink_record(&buf) < 0) {
5416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Unable to allocate new service record");
5426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
5446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
545cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		sink.record_id = add_service_record(conn, &buf);
5466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		free(buf.data);
547cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!sink.record_id) {
5486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Unable to register A2DP Sink service record");
5496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return -1;
5506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
5516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
5546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergvoid a2dp_exit()
5576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
558cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sink.sep) {
559cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_unregister_sep(sink.sep);
560cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		sink.sep = NULL;
561cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
5626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
563cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.sep) {
564cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_unregister_sep(source.sep);
565cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.sep = NULL;
566cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
5676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
568cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.record_id) {
569cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		remove_service_record(connection, source.record_id);
570cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.record_id = 0;
5716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
573cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (sink.record_id) {
574cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		remove_service_record(connection, sink.record_id);
575cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		sink.record_id = 0;
5766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	dbus_connection_unref(connection);
5796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
5826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	switch (freq) {
5836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_16000:
5846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_32000:
5856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 53;
5866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_44100:
5876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		switch (mode) {
5886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_MONO:
5896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
5906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 31;
5916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_STEREO:
5926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_JOINT_STEREO:
5936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 53;
5946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		default:
5956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Invalid channel mode %u", mode);
5966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 53;
5976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
5986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_48000:
5996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		switch (mode) {
6006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_MONO:
6016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
6026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 29;
6036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_STEREO:
6046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_JOINT_STEREO:
6056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 51;
6066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		default:
6076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Invalid channel mode %u", mode);
6086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 51;
6096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
6106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	default:
6116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("Invalid sampling freq %u", freq);
6126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 53;
6136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic gboolean select_sbc_params(struct sbc_codec_cap *cap,
6176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					struct sbc_codec_cap *supported)
6186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
6196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint max_bitpool, min_bitpool;
6206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(cap, 0, sizeof(struct sbc_codec_cap));
6226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
6246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->cap.media_codec_type = A2DP_CODEC_SBC;
6256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->frequency & A2DP_SAMPLING_FREQ_48000)
6276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_48000;
6286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_44100)
6296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_44100;
6306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_32000)
6316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_32000;
6326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_16000)
6336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_16000;
6346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
6356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported frequencies");
6366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
6376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->channel_mode & A2DP_CHANNEL_MODE_JOINT_STEREO)
6406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
6416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_STEREO)
6426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;
6436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_DUAL_CHANNEL)
6446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;
6456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_MONO)
6466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_MONO;
6476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
6486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported channel modes");
6496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
6506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->block_length & A2DP_BLOCK_LENGTH_16)
6536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_16;
6546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_12)
6556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_12;
6566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_8)
6576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_8;
6586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_4)
6596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_4;
6606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
6616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported block lengths");
6626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
6636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->subbands & A2DP_SUBBANDS_8)
6666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->subbands = A2DP_SUBBANDS_8;
6676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->subbands & A2DP_SUBBANDS_4)
6686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->subbands = A2DP_SUBBANDS_4;
6696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
6706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported subbands");
6716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
6726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->allocation_method & A2DP_ALLOCATION_LOUDNESS)
6756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
6766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->allocation_method & A2DP_ALLOCATION_SNR)
6776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->allocation_method = A2DP_ALLOCATION_SNR;
6786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
679cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	min_bitpool = MAX(default_bitpool(cap->frequency, cap->channel_mode),
6806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				supported->min_bitpool);
6816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
6826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				supported->max_bitpool);
6836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->min_bitpool = min_bitpool;
6856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->max_bitpool = max_bitpool;
6866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
6886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberggboolean a2dp_select_capabilities(struct avdtp_remote_sep *rsep, GSList **caps)
6916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
6926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *media_transport, *media_codec;
6936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap sbc_cap, *acp_sbc;
6946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_get_codec(rsep);
6966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (!media_codec)
6976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
6986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	acp_sbc = (void *) media_codec->data;
7006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
7026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						NULL, 0);
7036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_transport);
7056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	select_sbc_params(&sbc_cap, acp_sbc);
7076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
7096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sizeof(sbc_cap));
7106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_codec);
7126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
7146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7169494c146cec1df466c2f331957748beeac8d745aJohan Hedberggboolean a2dp_get_config(struct avdtp_stream *stream,
7179494c146cec1df466c2f331957748beeac8d745aJohan Hedberg				struct ipc_data_cfg **cfg, int *fd)
7186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
7196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *cap;
7206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_media_codec_capability *codec_cap = NULL;
7216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap *sbc_cap;
7226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_data_cfg *rsp;
7236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_codec_sbc *sbc;
7246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	GSList *caps;
7256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp = g_malloc0(sizeof(struct ipc_data_cfg) +
7276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				sizeof(struct ipc_codec_sbc));
7289494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	*fd = -1;
7296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc = (void *) rsp->data;
7306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7319494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	if (!avdtp_stream_get_transport(stream, fd, &rsp->pkt_len,
7326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					&caps)) {
7336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		g_free(rsp);
7346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	for (; caps; caps = g_slist_next(caps)) {
7386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap = caps->data;
7396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if (cap->category == AVDTP_MEDIA_CODEC) {
7406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			codec_cap = (void *) cap->data;
7416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
7436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (codec_cap == NULL) {
7466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		g_free(rsp);
7476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp->fd_opt = CFG_FD_OPT_WRITE;
7516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*cfg = rsp;
7536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (codec_cap->media_codec_type != A2DP_CODEC_SBC)
7556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return TRUE;
7566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap = (struct sbc_codec_cap *) codec_cap;
7586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp->channels = sbc_cap->channel_mode ==
7596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_CHANNEL_MODE_MONO ? 1 : 2;
7606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp->channel_mode = sbc_cap->channel_mode;
7616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp->sample_size = 2;
7626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	switch (sbc_cap->frequency) {
7646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_SAMPLING_FREQ_16000:
7656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			rsp->rate = 16000;
7666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_SAMPLING_FREQ_32000:
7686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			rsp->rate = 32000;
7696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_SAMPLING_FREQ_44100:
7716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			rsp->rate = 44100;
7726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_SAMPLING_FREQ_48000:
7746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			rsp->rate = 48000;
7756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	rsp->codec = CFG_CODEC_SBC;
7796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc->allocation = sbc_cap->allocation_method == A2DP_ALLOCATION_SNR ?
7806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				0x01 : 0x00;
7816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc->subbands = sbc_cap->subbands == A2DP_SUBBANDS_4 ? 4 : 8;
7826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	switch (sbc_cap->block_length) {
7846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_BLOCK_LENGTH_4:
7856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			sbc->blocks = 4;
7866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_BLOCK_LENGTH_8:
7886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			sbc->blocks = 8;
7896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_BLOCK_LENGTH_12:
7916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			sbc->blocks = 12;
7926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_BLOCK_LENGTH_16:
7946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			sbc->blocks = 16;
7956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
7966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc->bitpool = sbc_cap->max_bitpool;
7996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
8016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8021addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
803cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void discovery_complete(struct avdtp *session, GSList *seps, int err,
804cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				void *user_data)
8051addff77624b54445c9b81779ddc78892a126a45Johan Hedberg{
806cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_local_sep *lsep;
807cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_remote_sep *rsep;
808cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *caps = NULL;
809cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
810cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (err < 0) {
811cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("Discovery failed: %s (%d)", strerror(-err), -err);
812cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->stream = NULL;
813cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
814cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
815cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
8161addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
817cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("Discovery complete");
818cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
819cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
820cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				A2DP_CODEC_SBC, &lsep, &rsep) < 0) {
821cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("No matching ACP and INT SEPs found");
822cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
823cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
824cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
825cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
826cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!a2dp_select_capabilities(rsep, &caps)) {
827cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("Unable to select remote SEP capabilities");
828cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
829cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
830cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
831cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
832cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	err = avdtp_set_configuration(session, rsep, lsep, caps,
833cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg					&setup->stream);
834cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (err < 0) {
835cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("avdtp_set_configuration: %s", strerror(-err));
836cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
837cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
838cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
839cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
840cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	/* Notify sink.c of the new stream */
841cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	sink_new_stream(setup->dev, session, setup->stream);
842cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
843cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
844cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_cancel_stream(int id)
845cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
846cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
847cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *l;
848cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
849cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
850cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
851cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
852cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	for (cb_data = NULL, l = setup->cb; l != NULL; l = g_slist_next(l)) {
853cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		struct a2dp_stream_cb *cb = l->data;
854cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
855cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (cb->id == id) {
856cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			cb_data = cb;
857cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
858cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
859cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
860cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
861cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!cb_data)
862cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
863cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
864cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_remove(setup->cb, cb_data);
865cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
866cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup->cb)
867cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = TRUE;
868cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
869cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
870cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
871cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
872cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergint a2dp_source_request_stream(struct avdtp *session, struct device *dev,
873cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg					gboolean start, a2dp_stream_cb_t cb,
874cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg					void *user_data)
875cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
876cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
877cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	static unsigned int cb_id = 0;
878cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
879cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data = g_new(struct a2dp_stream_cb, 1);
880cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->cb = cb;
881cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->user_data = user_data;
882cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->id = cb_id++;
883cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
884cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup) {
885cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = FALSE;
886cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->cb = g_slist_append(setup->cb, cb_data);
887cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (start)
888cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			setup->start = TRUE;
889cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return cb_data->id;
890cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
891cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
892cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup = g_new0(struct a2dp_stream_setup, 1);
893cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->session = avdtp_ref(session);
894cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->dev = dev;
895cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_append(setup->cb, cb_data);
896cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->start = start;
897cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->stream = source.stream;
898cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
899cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	switch (avdtp_sep_get_state(source.sep)) {
900cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_IDLE:
901cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (avdtp_discover(session, discovery_complete, setup) < 0)
902cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
903cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
904cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
905cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!start) {
906cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
907cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
908cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
909cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (source.starting)
910cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
911cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (avdtp_start(session, source.stream) < 0)
912cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
913cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
914cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
915cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!start || !source.suspending) {
916cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
917cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			return cb_data->id;
918cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
919cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.start_requested = TRUE;
920cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
921cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
922cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		goto failed;
923cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
924cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
925cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return cb_data->id;
926cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
927cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergfailed:
928cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	stream_setup_free(setup);
929cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_id--;
930cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return -1;
931cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
932cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
933cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_lock(struct device *dev, struct avdtp *session)
934cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
935cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.used_by)
936cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
937cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
938cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.used_by = dev;
939cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
940cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
941cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
942cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
943cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_unlock(struct device *dev, struct avdtp *session)
944cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
945cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
946cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
947cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!source.sep)
948cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
949cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
950cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.used_by != dev)
951cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
952cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
953cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	state = avdtp_sep_get_state(source.sep);
954cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
955cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	source.used_by = NULL;
956cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
957cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!source.stream || state == AVDTP_STATE_IDLE)
958cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
959cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
960cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	switch (state) {
961cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
962cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		/* Set timer here */
963cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
964cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
965cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (avdtp_suspend(session, source.stream) == 0)
966cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			source.suspending = TRUE;
967cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
968cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
969cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
970cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
971cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
972cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
973cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
974cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
975cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_suspend(struct device *dev, struct avdtp *session)
976cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
977cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
978cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
979cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!source.sep)
980cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
981cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
982cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.used_by != dev)
983cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
984cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
985cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	state = avdtp_sep_get_state(source.sep);
986cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
987cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!source.stream || state != AVDTP_STATE_STREAMING)
988cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
989cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
990cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (avdtp_suspend(session, source.stream) == 0) {
991cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		source.suspending = TRUE;
992cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
993cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
994cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
995cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return FALSE;
996cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
997cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
998cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_start_stream(struct device *dev, struct avdtp *session)
999cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1000cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1001cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1002cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!source.sep)
1003cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1004cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1005cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (source.used_by != dev)
1006cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1007cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1008cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	state = avdtp_sep_get_state(source.sep);
1009cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1010cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state < AVDTP_STATE_OPEN) {
1011cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("a2dp_source_start_stream: no stream open");
1012cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1013cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1014cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1015cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state == AVDTP_STATE_STREAMING)
1016cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1017cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1018cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (avdtp_start(session, source.stream) < 0)
1019cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1020cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1021cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
10221addff77624b54445c9b81779ddc78892a126a45Johan Hedberg}
1023