a2dp.c revision f4211a3cd3442d54fa7877a6c421bee034d46e8e
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"
39d013a1eaa7beebbb49c1fe0015c70ad81566d97cJohan Hedberg#include "device.h"
406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "avdtp.h"
41f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg#include "sink.h"
42e929f72c17c104ed4eb6c15bda8f5d2be58c8084Johan Hedberg#include "a2dp.h"
436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
44c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg/* The duration that streams without users are allowed to stay in
45c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg * STREAMING state. */
46c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg#define SUSPEND_TIMEOUT 5000
47c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
48cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MIN
49cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MIN(x, y) ((x) < (y) ? (x) : (y))
50cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
51cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
52cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#ifndef MAX
53cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg# define MAX(x, y) ((x) > (y) ? (x) : (y))
54cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg#endif
55cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
56cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_sep {
57666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	uint8_t type;
58cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_local_sep *sep;
59c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	struct avdtp *session;
60cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
61cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct device *used_by;
62c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	guint suspend_timer;
63666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	gboolean locked;
64cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean start_requested;
65cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean suspending;
66cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean starting;
67cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
68cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
69cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_cb {
70cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	a2dp_stream_cb_t cb;
71cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	void *user_data;
72cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	int id;
73cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
74cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
75cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstruct a2dp_stream_setup {
76cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp *session;
77cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct device *dev;
78cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_stream *stream;
79cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean start;
80cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	gboolean canceled;
81cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *cb;
82cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg};
83cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic DBusConnection *connection = NULL;
856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
86666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic GSList *sinks = NULL;
87666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic GSList *sources = NULL;
88666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
89666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic uint32_t source_record_id = 0;
90666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic uint32_t sink_record_id = 0;
916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
92cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic struct a2dp_stream_setup *setup = NULL;
936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
94cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void stream_setup_free(struct a2dp_stream_setup *s)
95cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
96cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (s->session)
97cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_unref(s->session);
98cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_foreach(s->cb, (GFunc) g_free, NULL);
99cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_free(s->cb);
100cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_free(s);
101cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup = NULL;
102cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
103cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
104cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void setup_callback(struct a2dp_stream_cb *cb,
105cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				struct a2dp_stream_setup *s)
106cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
107cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb->cb(s->session, s->dev, s->stream, cb->user_data);
108cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
109cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
11078a94059160d7478624cad315022255f7ebbbe80Johan Hedbergstatic gboolean finalize_stream_setup(struct a2dp_stream_setup *s)
111cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
112cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	g_slist_foreach(setup->cb, (GFunc) setup_callback, setup);
113cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	stream_setup_free(setup);
11478a94059160d7478624cad315022255f7ebbbe80Johan Hedberg	return FALSE;
115cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1161addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
1177a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedbergstatic void stream_state_changed(struct avdtp_stream *stream,
1187a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					avdtp_state_t old_state,
1197a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					avdtp_state_t new_state,
1207a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					struct avdtp_error *err,
1217a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg					void *user_data)
1227a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg{
1237a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	struct a2dp_sep *sep = user_data;
1247a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1257a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (new_state != AVDTP_STATE_IDLE)
1267a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		return;
1277a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1287a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (sep->suspend_timer) {
1297a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		g_source_remove(sep->suspend_timer);
1307a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		sep->suspend_timer = 0;
1317a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	}
1327a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1337a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	if (sep->session) {
1347a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		avdtp_unref(sep->session);
1357a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		sep->session = NULL;
1367a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	}
1377a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
1387a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	sep->stream = NULL;
1397a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg}
1407a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg
141f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedbergstatic gboolean setconf_ind(struct avdtp *session,
142f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				struct avdtp_local_sep *sep,
1436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct avdtp_stream *stream,
144f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg				GSList *caps, uint8_t *err,
145666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *category, void *user_data)
1466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
147666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
148f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	struct device *dev;
149f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	bdaddr_t addr;
150f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
151666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Ind");
153666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
154c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Set_Configuration_Ind");
155f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
156f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	avdtp_get_peers(session, NULL, &addr);
157f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
158f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	dev = manager_device_connected(&addr, A2DP_SOURCE_UUID);
159f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	if (!dev) {
160f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
161f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		*category = 0x00;
162f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg		return FALSE;
163f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg	}
164f817fefff69cc44d5a2e1ba7d8ed9976fe3b4235Johan Hedberg
1657a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
166c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->stream = stream;
167cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
168666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
169c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		sink_new_stream(dev, session, stream);
1706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
1726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
1736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
174f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep,
175666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				GSList **caps, uint8_t *err, void *user_data)
1766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
177666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
1786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *media_transport, *media_codec;
1796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap sbc_cap;
1806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
181666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Capability_Ind");
1836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
1846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Capability_Ind");
1856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = NULL;
1876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
1896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						NULL, 0);
1906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_transport);
1926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&sbc_cap, 0, sizeof(struct sbc_codec_cap));
1946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
1966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
1976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.frequency = ( A2DP_SAMPLING_FREQ_48000 |
1996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_44100 |
2006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_32000 |
2016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				A2DP_SAMPLING_FREQ_16000 );
2026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.channel_mode = ( A2DP_CHANNEL_MODE_JOINT_STEREO |
2046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_STEREO |
2056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_DUAL_CHANNEL |
2066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_CHANNEL_MODE_MONO );
2076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.block_length = ( A2DP_BLOCK_LENGTH_16 |
2096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_12 |
2106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_8 |
2116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_BLOCK_LENGTH_4 );
2126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.subbands = ( A2DP_SUBBANDS_8 | A2DP_SUBBANDS_4 );
2146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.allocation_method = ( A2DP_ALLOCATION_LOUDNESS |
2166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					A2DP_ALLOCATION_SNR );
2176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.min_bitpool = 2;
2196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_cap.max_bitpool = 250;
2206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
2226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sizeof(sbc_cap));
2236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_codec);
2256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
2266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
2276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
229f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
2300f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg				struct avdtp_stream *stream,
231666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_error *err, void *user_data)
2326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
233666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
2340f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	int ret;
235cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
236666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
2376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
238666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
239c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Set_Configuration_Cfm");
240cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
2410f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
2420f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (setup)
2430f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			finalize_stream_setup(setup);
2440f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		return;
2450f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
2460f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
2477a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
248c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->stream = stream;
249cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
250cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
251cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
252cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
2530f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	ret = avdtp_open(session, stream);
2540f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (ret < 0) {
2550f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		error("Error on avdtp_open %s (%d)", strerror(-ret),
2560f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg				-ret);
2577a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg		setup->stream = NULL;
258cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
259cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
2606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
262f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
263666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *err, void *user_data)
2646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
265666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
266666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
267666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
2686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Get_Configuration_Ind");
2696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Get_Configuration_Ind");
2716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
2726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
274f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
275666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
276666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
2776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
278666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
279666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
280666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
2816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Set_Configuration_Cfm");
2826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Set_Configuration_Cfm");
2846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
286f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
287666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
288666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
2896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
290666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
291666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
292666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
2936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Ind");
2946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
2956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Ind");
2966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
2976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
2986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
299f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
300666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
301666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
3026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
303666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
304666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
305666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
3066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Open_Cfm");
3076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
3086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Open_Cfm");
3091addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
310cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
3111addff77624b54445c9b81779ddc78892a126a45Johan Hedberg		return;
3121addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
313cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
3140f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (!err)
3150f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			avdtp_close(session, stream);
316cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
317cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
318cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
319cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
3200f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
3210f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		setup->stream = NULL;
3220f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		goto finalize;
3230f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
3240f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
325cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->start) {
326cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (avdtp_start(session, stream) == 0)
327cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			return;
3281addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
329cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("avdtp_start failed");
330cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->stream = NULL;
331cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
332cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
3330f458da19471c933a4105cc450c48548b72edc8eJohan Hedbergfinalize:
334cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	finalize_stream_setup(setup);
3356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
337c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedbergstatic gboolean suspend_timeout(struct a2dp_sep *sep)
338c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg{
339c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	if (avdtp_suspend(sep->session, sep->stream) == 0)
340c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		sep->suspending = TRUE;
341c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
3427a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg	sep->suspend_timer = 0;
343c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
344c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	avdtp_unref(sep->session);
345c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	sep->session = NULL;
346c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
347c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	return FALSE;
348c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg}
349c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
350f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep,
351666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
352666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
3536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
354666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
355c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
356666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
3576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Ind");
358666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
3596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Ind");
3605b5cfaadb312600c58362617080e29fbf036712cJohan Hedberg
361c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->session = avdtp_ref(session);
362c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
363c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->suspend_timer = g_timeout_add(SUSPEND_TIMEOUT,
364c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg						(GSourceFunc) suspend_timeout,
365c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg						a2dp_sep);
366c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	return TRUE;
3676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
369f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
370666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
371666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
3726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
373666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
374666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
375666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
3766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Start_Cfm");
3776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
3786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Start_Cfm");
379cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
380cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
381cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
382cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
383cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup->canceled) {
3840f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (!err)
3850f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			avdtp_close(session, stream);
386cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		stream_setup_free(setup);
387cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
388cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
389cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
3900f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err)
3910f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		setup->stream = NULL;
3920f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
393cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	finalize_stream_setup(setup);
3946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
396f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
397666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
398666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
3996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
400666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
401666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
402666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Ind");
4046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
4056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Suspend_Ind");
4066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
409f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
410666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
411666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
4126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
413666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
414c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
415666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Suspend_Cfm");
417666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
418c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Suspend_Cfm");
419cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
420c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	a2dp_sep->suspending = FALSE;
421cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
4220f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	if (err) {
423c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		a2dp_sep->start_requested = FALSE;
4240f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		if (setup)
4250f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg			finalize_stream_setup(setup);
4260f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg		return;
4270f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	}
4280f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg
429c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg	if (a2dp_sep->start_requested) {
430cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		avdtp_start(session, stream);
431c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		a2dp_sep->start_requested = FALSE;
432cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
4336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
435f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
436666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
437666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
4386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
439666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
440c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
441666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Ind");
443666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
444c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Close_Ind");
445cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
4466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
449f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
450666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
451666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
4526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
453666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
454c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
455666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Close_Cfm");
457666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
458c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Close_Cfm");
4596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
461f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
462666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				struct avdtp_stream *stream, uint8_t *err,
463666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				void *user_data)
4646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
465666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
466c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
467666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Ind");
469666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
470c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg		debug("SBC Source: Abort_Ind");
471cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
4726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
475f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
476666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
477666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
4786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
479666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
480c0e0aa5745b38505b180ffdd7d5df44612597e75Johan Hedberg
481666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: Abort_Cfm");
483666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	else
4846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: Abort_Cfm");
4856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
487f9d8837abad3b67b70425157ac854deb892b2b91Johan Hedbergstatic gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
488666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				uint8_t *err, void *user_data)
4896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
490666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
491666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
492666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
4936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Ind");
4946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
4956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Ind");
4966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
4976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4990f458da19471c933a4105cc450c48548b72edc8eJohan Hedbergstatic void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
500666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			struct avdtp_stream *stream, struct avdtp_error *err,
501666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			void *user_data)
5026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
503666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *a2dp_sep = user_data;
504666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
505666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
5066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Sink: ReConfigure_Cfm");
5076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		debug("SBC Source: ReConfigure_Cfm");
5096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_cfm cfm = {
5126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_cfm,
5136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_cfm,
5146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_cfm,
5156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_cfm,
5166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_cfm,
5176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_cfm,
5186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_cfm,
5196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_cfm
5206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
5216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic struct avdtp_sep_ind ind = {
5236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_capability		= getcap_ind,
5246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.set_configuration	= setconf_ind,
5256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.get_configuration	= getconf_ind,
5266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.open			= open_ind,
5276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start			= start_ind,
5286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.suspend		= suspend_ind,
5296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close			= close_ind,
5306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.abort			= abort_ind,
5316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.reconfigure		= reconf_ind
5326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
5336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_source_record(sdp_buf_t *buf)
5356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
5366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
5376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uuid_t root_uuid, l2cap, avdtp, a2src;
5386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_profile_desc_t profile[1];
5396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_t *aproto, *proto[2];
5406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_record_t record;
5416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_data_t *psm, *version, *features;
5426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t lp = AVDTP_UUID, ver = 0x0100, feat = 0x000F;
5436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int ret = 0;
5446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(&record, 0, sizeof(sdp_record_t));
5466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
5486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	root = sdp_list_append(0, &root_uuid);
5496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_browse_groups(&record, root);
5506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
5526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	svclass_id = sdp_list_append(0, &a2src);
5536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_service_classes(&record, svclass_id);
5546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
5566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	profile[0].version = 0x0100;
5576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	pfseq = sdp_list_append(0, &profile[0]);
5586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_profile_descs(&record, pfseq);
5596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&l2cap, L2CAP_UUID);
5616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(0, &l2cap);
5626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	psm = sdp_data_alloc(SDP_UINT16, &lp);
5636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[0] = sdp_list_append(proto[0], psm);
5646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(0, proto[0]);
5656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_uuid16_create(&avdtp, AVDTP_UUID);
5676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(0, &avdtp);
5686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	version = sdp_data_alloc(SDP_UINT16, &ver);
5696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	proto[1] = sdp_list_append(proto[1], version);
5706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	apseq = sdp_list_append(apseq, proto[1]);
5716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	aproto = sdp_list_append(0, apseq);
5736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_access_protos(&record, aproto);
5746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	features = sdp_data_alloc(SDP_UINT16, &feat);
5766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
5776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_set_info_attr(&record, "Audio Source", 0, 0);
5796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (sdp_gen_record_pdu(&record, buf) < 0)
5816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = -1;
5826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = 0;
5846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(psm);
5866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	free(version);
5876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[0], 0);
5886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(proto[1], 0);
5896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(apseq, 0);
5906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(pfseq, 0);
5916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(aproto, 0);
5926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(root, 0);
5936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(svclass_id, 0);
5946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);
5956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_list_free(record.pattern, free);
5966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
5986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
5996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int a2dp_sink_record(sdp_buf_t *buf)
6016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
6026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
6036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
605666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type)
6066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
607666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep;
608666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList **l;
609666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	int (*create_record)(sdp_buf_t *buf);
610666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	uint32_t *record_id;
6116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sdp_buf_t buf;
6126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
613666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep = g_new0(struct a2dp_sep, 1);
614666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
615666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO,
616666938b54d631956826343ed278e2af4b982fc29Johan Hedberg					&ind, &cfm, sep);
617666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (sep->sep == NULL) {
618666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
619666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
620666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
621666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
622666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->type = type;
623666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
624666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (type == AVDTP_SEP_TYPE_SOURCE) {
625666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		l = &sources;
626666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		create_record = a2dp_source_record;
627666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		record_id = &source_record_id;
628666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	} else {
629666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		l = &sinks;
630666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		create_record = a2dp_sink_record;
631666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		record_id = &sink_record_id;
632666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
633666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
634666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (*record_id != 0)
635666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		goto add;
636666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
637666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (create_record(&buf) < 0) {
638666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("Unable to allocate new service record");
639666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		avdtp_unregister_sep(sep->sep);
640666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
641666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
642666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
643666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
644666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	*record_id = add_service_record(conn, &buf);
645666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	free(buf.data);
646666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!*record_id) {
647666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("Unable to register A2DP service record");
648666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		avdtp_unregister_sep(sep->sep);
649666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		g_free(sep);
650666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return NULL;
651666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
652666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
653666938b54d631956826343ed278e2af4b982fc29Johan Hedbergadd:
654666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	*l = g_slist_append(*l, sep);
655666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
656666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	return sep;
657666938b54d631956826343ed278e2af4b982fc29Johan Hedberg}
658666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
659666938b54d631956826343ed278e2af4b982fc29Johan Hedbergint a2dp_init(DBusConnection *conn, gboolean enable_sink, gboolean enable_source)
660666938b54d631956826343ed278e2af4b982fc29Johan Hedberg{
6616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (!enable_sink && !enable_source)
6626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 0;
6636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	connection = dbus_connection_ref(conn);
6656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	avdtp_init();
6676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (enable_sink) {
669666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE);
670666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE);
6716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
673666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (enable_source)
674666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK);
6756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
6766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
6776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
6786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
679666938b54d631956826343ed278e2af4b982fc29Johan Hedbergstatic void a2dp_unregister_sep(struct a2dp_sep *sep)
680666938b54d631956826343ed278e2af4b982fc29Johan Hedberg{
681666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	avdtp_unregister_sep(sep->sep);
682666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_free(sep);
683666938b54d631956826343ed278e2af4b982fc29Johan Hedberg}
684666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
6856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergvoid a2dp_exit()
6866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
687666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_foreach(sinks, (GFunc) a2dp_unregister_sep, NULL);
688666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_free(sinks);
689666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sinks = NULL;
6906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
691666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_foreach(sources, (GFunc) a2dp_unregister_sep, NULL);
692666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	g_slist_free(sources);
693666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sources = NULL;
6946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
695666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (source_record_id) {
696666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		remove_service_record(connection, source_record_id);
697666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		source_record_id = 0;
6986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
6996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
700666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (sink_record_id) {
701666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		remove_service_record(connection, sink_record_id);
702666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sink_record_id = 0;
7036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	dbus_connection_unref(connection);
7066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
7096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	switch (freq) {
7106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_16000:
7116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_32000:
7126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 53;
7136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_44100:
7146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		switch (mode) {
7156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_MONO:
7166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
7176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 31;
7186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_STEREO:
7196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_JOINT_STEREO:
7206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 53;
7216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		default:
7226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Invalid channel mode %u", mode);
7236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 53;
7246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
7256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	case A2DP_SAMPLING_FREQ_48000:
7266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		switch (mode) {
7276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_MONO:
7286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
7296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 29;
7306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_STEREO:
7316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		case A2DP_CHANNEL_MODE_JOINT_STEREO:
7326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 51;
7336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		default:
7346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			error("Invalid channel mode %u", mode);
7356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return 51;
7366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
7376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	default:
7386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("Invalid sampling freq %u", freq);
7396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return 53;
7406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic gboolean select_sbc_params(struct sbc_codec_cap *cap,
7446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					struct sbc_codec_cap *supported)
7456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
7466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint max_bitpool, min_bitpool;
7476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(cap, 0, sizeof(struct sbc_codec_cap));
7496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
7516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->cap.media_codec_type = A2DP_CODEC_SBC;
7526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->frequency & A2DP_SAMPLING_FREQ_48000)
7546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_48000;
7556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_44100)
7566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_44100;
7576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_32000)
7586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_32000;
7596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->frequency & A2DP_SAMPLING_FREQ_16000)
7606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->frequency = A2DP_SAMPLING_FREQ_16000;
7616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
7626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported frequencies");
7636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->channel_mode & A2DP_CHANNEL_MODE_JOINT_STEREO)
7676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
7686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_STEREO)
7696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;
7706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_DUAL_CHANNEL)
7716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;
7726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->channel_mode & A2DP_CHANNEL_MODE_MONO)
7736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->channel_mode = A2DP_CHANNEL_MODE_MONO;
7746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
7756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported channel modes");
7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->block_length & A2DP_BLOCK_LENGTH_16)
7806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_16;
7816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_12)
7826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_12;
7836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_8)
7846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_8;
7856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->block_length & A2DP_BLOCK_LENGTH_4)
7866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->block_length = A2DP_BLOCK_LENGTH_4;
7876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
7886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported block lengths");
7896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
7916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->subbands & A2DP_SUBBANDS_8)
7936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->subbands = A2DP_SUBBANDS_8;
7946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->subbands & A2DP_SUBBANDS_4)
7956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->subbands = A2DP_SUBBANDS_4;
7966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
7976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		error("No supported subbands");
7986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
7996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
8006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (supported->allocation_method & A2DP_ALLOCATION_LOUDNESS)
8026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
8036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (supported->allocation_method & A2DP_ALLOCATION_SNR)
8046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		cap->allocation_method = A2DP_ALLOCATION_SNR;
8056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8068ae40e0b0046a011bbc15771f248d7950a606ae4Johan Hedberg	min_bitpool = MAX(2, supported->min_bitpool);
8076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
8086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				supported->max_bitpool);
8096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->min_bitpool = min_bitpool;
8116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	cap->max_bitpool = max_bitpool;
8126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
8146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8165d5f4d99e9176da5f01b7195e6132b5796d026d8Johan Hedbergstatic gboolean a2dp_select_capabilities(struct avdtp_remote_sep *rsep, GSList **caps)
8176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
8186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct avdtp_service_capability *media_transport, *media_codec;
8196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct sbc_codec_cap sbc_cap, *acp_sbc;
8206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_get_codec(rsep);
8226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (!media_codec)
8236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return FALSE;
8246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	acp_sbc = (void *) media_codec->data;
8266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
8286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						NULL, 0);
8296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_transport);
8316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	select_sbc_params(&sbc_cap, acp_sbc);
8336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
8356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sizeof(sbc_cap));
8366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	*caps = g_slist_append(*caps, media_codec);
8386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return TRUE;
8406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
842cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergstatic void discovery_complete(struct avdtp *session, GSList *seps, int err,
843cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				void *user_data)
8441addff77624b54445c9b81779ddc78892a126a45Johan Hedberg{
845cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_local_sep *lsep;
846cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct avdtp_remote_sep *rsep;
847cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *caps = NULL;
848cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
849cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (err < 0) {
850cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("Discovery failed: %s (%d)", strerror(-err), -err);
851cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->stream = NULL;
852cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
853cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
854cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
8551addff77624b54445c9b81779ddc78892a126a45Johan Hedberg
856cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	debug("Discovery complete");
857cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
858cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
859cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg				A2DP_CODEC_SBC, &lsep, &rsep) < 0) {
860cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("No matching ACP and INT SEPs found");
861cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
862cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
863cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
864cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
865cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!a2dp_select_capabilities(rsep, &caps)) {
866cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("Unable to select remote SEP capabilities");
867cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
868cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
869cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
870cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
871cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	err = avdtp_set_configuration(session, rsep, lsep, caps,
872cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg					&setup->stream);
873cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (err < 0) {
874cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("avdtp_set_configuration: %s", strerror(-err));
875cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		finalize_stream_setup(setup);
876cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return;
877cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
878cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
879cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	/* Notify sink.c of the new stream */
880cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	sink_new_stream(setup->dev, session, setup->stream);
881cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
882cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
883cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_cancel_stream(int id)
884cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
885cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
886cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	GSList *l;
887cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
888cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup)
889cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
890cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
891cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	for (cb_data = NULL, l = setup->cb; l != NULL; l = g_slist_next(l)) {
892cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		struct a2dp_stream_cb *cb = l->data;
893cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
894cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (cb->id == id) {
895cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			cb_data = cb;
896cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
897cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
898cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
899cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
900cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!cb_data)
901cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
902cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
903cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_remove(setup->cb, cb_data);
9049ce01693dd0aa7407b7d8eb37c8524dd05abe15cJohan Hedberg	g_free(cb_data);
905cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
906cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (!setup->cb)
907cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = TRUE;
908cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
909cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
910cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
911cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
9120f458da19471c933a4105cc450c48548b72edc8eJohan Hedbergunsigned int a2dp_source_request_stream(struct avdtp *session,
913666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						struct device *dev,
914666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						gboolean start,
915666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						a2dp_stream_cb_t cb,
916666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						void *user_data,
917666938b54d631956826343ed278e2af4b982fc29Johan Hedberg						struct a2dp_sep **ret)
918cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
919cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	struct a2dp_stream_cb *cb_data;
920cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	static unsigned int cb_id = 0;
921666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
922666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
923cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
924666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
925666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
926666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
927666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->locked)
928666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			continue;
929666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
930666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->used_by == NULL || tmp->used_by == dev) {
931666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
932666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
933666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
934666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
935666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
936666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep) {
937666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		error("a2dp_source_request_stream: no available SEP found");
938730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		return 0;
939730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg	}
940730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
941730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg	if (setup && setup->dev != dev) {
942730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		error("a2dp_source_request_stream: stream setup in progress "
943730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg				"already for another device");
944730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		return 0;
945730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg	}
946730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
947666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->used_by = dev;
948666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
949666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	debug("a2dp_source_request_stream: selected SEP %p", sep);
950666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
951cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data = g_new(struct a2dp_stream_cb, 1);
952cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->cb = cb;
953cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_data->user_data = user_data;
9540f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	cb_data->id = ++cb_id;
955cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
956cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (setup) {
957cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->canceled = FALSE;
958cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		setup->cb = g_slist_append(setup->cb, cb_data);
959cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (start)
960cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			setup->start = TRUE;
961cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return cb_data->id;
962cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
963cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
964cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup = g_new0(struct a2dp_stream_setup, 1);
965cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->session = avdtp_ref(session);
966cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->dev = dev;
967cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->cb = g_slist_append(setup->cb, cb_data);
968cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	setup->start = start;
969666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	setup->stream = sep->stream;
970cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
971666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	switch (avdtp_sep_get_state(sep->sep)) {
972cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_IDLE:
973730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		if (avdtp_discover(session, discovery_complete, setup) < 0) {
974730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg			error("avdtp_discover failed");
975cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
976730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		}
977cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
978cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
979cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		if (!start) {
980cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
981cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
982cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
983666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (sep->starting)
984cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			break;
985666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (avdtp_start(session, sep->stream) < 0) {
986730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg			error("avdtp_start failed");
987cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			goto failed;
988730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		}
989cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
990cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
991666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (!start || !sep->suspending) {
992666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			if (sep->suspend_timer) {
993666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				g_source_remove(sep->suspend_timer);
994666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				sep->suspend_timer = 0;
99558b173171f61373c7eb8ed00d0635fb06fa741ccJohan Hedberg			}
996666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			if (sep->session) {
997666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				avdtp_unref(sep->session);
998666938b54d631956826343ed278e2af4b982fc29Johan Hedberg				sep->session = NULL;
9997a29d3596b6680c421aa28051ec6baeea1bbfa6bJohan Hedberg			}
1000cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			g_idle_add((GSourceFunc) finalize_stream_setup, setup);
1001cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg			return cb_data->id;
1002cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		}
1003666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sep->start_requested = TRUE;
1004cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1005cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
1006730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg		error("SEP in bad state for requesting a new stream");
1007cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		goto failed;
1008cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1009666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1010666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (ret)
1011666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		*ret = sep;
1012cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1013cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return cb_data->id;
1014cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1015cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedbergfailed:
1016cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	stream_setup_free(setup);
1017cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	cb_id--;
10180f458da19471c933a4105cc450c48548b72edc8eJohan Hedberg	return 0;
1019cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1020cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1021cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_lock(struct device *dev, struct avdtp *session)
1022cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1023666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1024cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1025666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1026666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *sep = l->data;
1027730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
1028666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (sep->locked)
1029666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			continue;
1030cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1031f4211a3cd3442d54fa7877a6c421bee034d46e8eJohan Hedberg		if (sep->used_by != dev)
1032f4211a3cd3442d54fa7877a6c421bee034d46e8eJohan Hedberg			continue;
1033f4211a3cd3442d54fa7877a6c421bee034d46e8eJohan Hedberg
1034666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		debug("SBC Source SEP %p locked", sep);
1035666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sep->locked = TRUE;
1036666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		return TRUE;
1037666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1038666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1039666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	return FALSE;
1040cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1041cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1042cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_unlock(struct device *dev, struct avdtp *session)
1043cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1044cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1045666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1046666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1047cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1048666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1049666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1050666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1051f4211a3cd3442d54fa7877a6c421bee034d46e8eJohan Hedberg		if (!tmp->locked)
1052666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			continue;
1053666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1054666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->sep && tmp->used_by == dev) {
1055666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1056666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1057666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1058666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1059cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1060666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep)
1061cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1062cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1063666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1064cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1065666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->locked = FALSE;
1066666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	sep->used_by = NULL;
1067cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1068666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	debug("SBC Source SEP %p unlocked", sep);
1069730a4ceb9e7e986e2a327fa7e023c3dd2102a50dJohan Hedberg
1070666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep->stream || state == AVDTP_STATE_IDLE)
1071cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1072cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1073cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	switch (state) {
1074cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_OPEN:
1075cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		/* Set timer here */
1076cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1077cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	case AVDTP_STATE_STREAMING:
1078666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (avdtp_suspend(session, sep->stream) == 0)
1079666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep->suspending = TRUE;
1080cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1081cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	default:
1082cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		break;
1083cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1084cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1085cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
1086cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1087cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1088cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_suspend(struct device *dev, struct avdtp *session)
1089cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1090cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1091666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1092666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1093cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1094666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1095666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1096cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1097666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->sep && tmp->used_by == dev) {
1098666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1099666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1100666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1101666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1102666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1103666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep)
1104cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1105cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1106666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1107cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1108666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep->stream || state != AVDTP_STATE_STREAMING)
1109cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1110cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1111666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (avdtp_suspend(session, sep->stream) == 0) {
1112666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		sep->suspending = TRUE;
1113cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1114cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1115cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1116cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return FALSE;
1117cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg}
1118cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1119cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberggboolean a2dp_source_start_stream(struct device *dev, struct avdtp *session)
1120cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg{
1121cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	avdtp_state_t state;
1122666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	GSList *l;
1123666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	struct a2dp_sep *sep = NULL;
1124cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1125666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	for (l = sources; l != NULL; l = l->next) {
1126666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		struct a2dp_sep *tmp = l->data;
1127666938b54d631956826343ed278e2af4b982fc29Johan Hedberg
1128666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		if (tmp->sep && tmp->used_by == dev) {
1129666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			sep = tmp;
1130666938b54d631956826343ed278e2af4b982fc29Johan Hedberg			break;
1131666938b54d631956826343ed278e2af4b982fc29Johan Hedberg		}
1132666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	}
1133cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1134666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (!sep)
1135cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1136cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1137666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	state = avdtp_sep_get_state(sep->sep);
1138cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1139cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state < AVDTP_STATE_OPEN) {
1140cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		error("a2dp_source_start_stream: no stream open");
1141cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1142cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	}
1143cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1144cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	if (state == AVDTP_STATE_STREAMING)
1145cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return TRUE;
1146cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1147666938b54d631956826343ed278e2af4b982fc29Johan Hedberg	if (avdtp_start(session, sep->stream) < 0)
1148cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg		return FALSE;
1149cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg
1150cdd9e2e17ad674e5fc1a5ed19643880ef61d28c7Johan Hedberg	return TRUE;
11511addff77624b54445c9b81779ddc78892a126a45Johan Hedberg}
1152