All pastes #792531 Raw Edit

Mine

public text v1 · immutable
·published 2007-11-21 14:27 UTC
rendered paste body
diff --git a/audio/Makefile.am b/audio/Makefile.am
index 48c2a80..9484549 100644
--- a/audio/Makefile.am
+++ b/audio/Makefile.am
@@ -3,7 +3,7 @@ if AUDIOSERVICE
 if CONFIGFILES
 confdir = $(sysconfdir)/bluetooth
 
-conf_DATA = audio.service
+conf_DATA = audio.service audio.conf
 endif
 
 servicedir = $(libdir)/bluetooth
@@ -23,12 +23,12 @@ alsadir = $(libdir)/alsa-lib
 
 alsa_LTLIBRARIES = libasound_module_pcm_bluetooth.la libasound_module_ctl_bluetooth.la
 
-libasound_module_pcm_bluetooth_la_SOURCES = pcm_bluetooth.c ipc.h rtp.h
+libasound_module_pcm_bluetooth_la_SOURCES = pcm_bluetooth.c rtp.h ipc.h ipc.c
 libasound_module_pcm_bluetooth_la_LDFLAGS = -module -avoid-version -export-symbols-regex [_]*snd_pcm_.*
 libasound_module_pcm_bluetooth_la_LIBADD = @SBC_LIBS@ @ALSA_LIBS@
 libasound_module_pcm_bluetooth_la_CFLAGS = @ALSA_CFLAGS@ @SBC_CFLAGS@
 
-libasound_module_ctl_bluetooth_la_SOURCES = ctl_bluetooth.c ipc.h
+libasound_module_ctl_bluetooth_la_SOURCES = ctl_bluetooth.c rtp.h ipc.h ipc.c
 libasound_module_ctl_bluetooth_la_LDFLAGS = -module -avoid-version -export-symbols-regex [_]*snd_ctl_.*
 libasound_module_ctl_bluetooth_la_LIBADD = @ALSA_LIBS@
 libasound_module_ctl_bluetooth_la_CFLAGS = @ALSA_CFLAGS@
@@ -39,12 +39,13 @@ gstreamerdir = $(libdir)/gstreamer-0.10
 
 gstreamer_LTLIBRARIES = libgstbluetooth.la
 
-libgstbluetooth_la_SOURCES = gstbluetooth.c ipc.h rtp.h \
+libgstbluetooth_la_SOURCES = gstbluetooth.c \
 				gstsbcenc.h gstsbcenc.c \
 				gstsbcdec.h gstsbcdec.c \
 				gstsbcparse.h gstsbcparse.c \
 				gsta2dpsink.h gsta2dpsink.c \
-				gstsbcutil.h gstsbcutil.c
+				gstsbcutil.h gstsbcutil.c \
+				rtp.h ipc.h ipc.c
 libgstbluetooth_la_LDFLAGS = -module -avoid-version -export-symbols-regex gst_plugin_desc
 libgstbluetooth_la_LIBADD = @SBC_LIBS@ @GSTREAMER_LIBS@ -lgstaudio-0.10
 libgstbluetooth_la_CFLAGS = @GSTREAMER_CFLAGS@ @SBC_CFLAGS@
@@ -58,3 +59,4 @@ INCLUDES = -I$(top_srcdir)/common
 EXTRA_DIST = audio.service audio.conf audio-api.txt test-audio asound.conf
 
 MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/audio/ctl_bluetooth.c b/audio/ctl_bluetooth.c
index 9e1c320..7467758 100644
--- a/audio/ctl_bluetooth.c
+++ b/audio/ctl_bluetooth.c
@@ -65,7 +65,7 @@ static void bluetooth_exit(struct bluetooth_data *data)
 		return;
 
 	if (data->sock >= 0)
-		close(data->sock);
+		bt_audio_service_close(data->sock);
 
 	free(data);
 }
@@ -141,32 +141,48 @@ static int bluetooth_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
 }
 
 static int bluetooth_send_ctl(struct bluetooth_data *data,
-				struct ipc_packet *pkt, int len)
+			uint8_t mode, uint8_t key, struct bt_control_rsp *ctl_rsp)
 {
 	int ret;
+	struct bt_control_req *ctl_req = (void *) ctl_rsp;
 
-	ret = send(data->sock, pkt, len, MSG_NOSIGNAL);
+	memset(ctl_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+	ctl_req->h.msg_type = BT_CONTROL_REQ;
+	ctl_req->mode = mode;
+	ctl_req->key = key;
+
+	ret = send(data->sock, ctl_req, BT_AUDIO_IPC_PACKET_SIZE, MSG_NOSIGNAL);
 	if (ret <= 0) {
 		SYSERR("Unable to request new volume value to server");
 		return  -errno;
 	}
 
-	ret = recv(data->sock, pkt, len, 0);
+	ret = recv(data->sock, ctl_rsp, BT_AUDIO_IPC_PACKET_SIZE, 0);
 	if (ret <= 0) {
-		SYSERR("Unable to receive new volume value from server");
+		SNDERR("Unable to receive new volume value from server");
 		return  -errno;
 	}
 
-	if(pkt->type != PKT_TYPE_CTL_RSP) {
-		SNDERR("Unexpected packet type %d received", pkt->type);
+	if (ctl_rsp->h.msg_type > BT_MSG_MAX) {
+		SNDERR("Bogus message type %d "
+				"received from audio service",
+				ctl_rsp->h.msg_type);
 		return -EINVAL;
 	}
 
-	if(pkt->length != sizeof(struct ipc_data_ctl)) {
-		SNDERR("Unexpected packet length %d received", pkt->length);
+	if (ctl_rsp->h.msg_type != BT_CONTROL_RSP) {
+		SNDERR("Unexpected message %s received",
+				bt_audio_strmsg[ctl_rsp->h.msg_type]);
 		return -EINVAL;
 	}
 
+	if (ctl_rsp->posix_errno != 0) {
+		SNDERR("BT_CONTROL failed : %s (%d)",
+					strerror(ctl_rsp->posix_errno),
+					ctl_rsp->posix_errno);
+		return -ctl_rsp->posix_errno;
+	}
+
 	return 0;
 }
 
@@ -174,28 +190,20 @@ static int bluetooth_read_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
 								long *value)
 {
 	struct bluetooth_data *data = ext->private_data;
-	struct ipc_packet *pkt;
-	struct ipc_data_ctl *ctl;
-	int len, ret;
+	int ret;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_control_rsp *rsp = (void *) buf;
 
 	DBG("ext %p key %ld", ext, key);
 
-	len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl);
-	pkt = malloc(len);
-	memset(pkt, 0, len);
+	memset(buf, 0, sizeof(buf));
 	*value = 0;
 
-	pkt->type = PKT_TYPE_CTL_REQ;
-	pkt->length = sizeof(struct ipc_data_ctl);
-	ctl = (struct ipc_data_ctl *) pkt->data;
-	ctl->mode = key;
-
-	if ((ret = bluetooth_send_ctl(data, pkt, len)) < 0)
+	if ((ret = bluetooth_send_ctl(data, key, 0, rsp)) < 0)
 		goto done;
 
-	*value = ctl->key;
+	*value = rsp->key;
 done:
-	free(pkt);
 	return ret;
 }
 
@@ -203,10 +211,10 @@ static int bluetooth_write_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
 								long *value)
 {
 	struct bluetooth_data *data = ext->private_data;
-	struct ipc_packet *pkt;
-	struct ipc_data_ctl *ctl;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_control_rsp *rsp = (void *) buf;
 	long current;
-	int len, ret;
+	int ret, keyvalue;
 
 	DBG("ext %p key %ld", ext, key);
 
@@ -216,25 +224,15 @@ static int bluetooth_write_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
 	if (*value == current)
 		return 0;
 
-	len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl);
-	pkt = malloc(len);
-	memset(pkt, 0, len);
-
-	pkt->length = sizeof(struct ipc_data_ctl);
-	ctl = (struct ipc_data_ctl *) pkt->data;
-	ctl->mode = key;
-
 	while (*value != current) {
-		pkt->type = PKT_TYPE_CTL_REQ;
-		ctl->key = (*value > current) ? CTL_KEY_VOL_UP : CTL_KEY_VOL_DOWN;
+		keyvalue = (*value > current) ? BT_CONTROL_KEY_VOL_UP : BT_CONTROL_KEY_VOL_DOWN;
 
-		if ((ret = bluetooth_send_ctl(data, pkt, len)) < 0)
+		if ((ret = bluetooth_send_ctl(data, key, keyvalue, rsp)) < 0)
 			break;
 
-		current = ctl->key;
+		current = keyvalue;
 	}
 
-	free(pkt);
 	return ret;
 }
 
@@ -242,33 +240,30 @@ static int bluetooth_read_event(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id,
 						unsigned int *event_mask)
 {
 	struct bluetooth_data *data = ext->private_data;
-	struct ipc_packet *pkt;
-	struct ipc_data_ctl *ctl;
-	int len, ret;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_control_ind *ind = (void *) buf;
+	int ret;
 
 	DBG("ext %p id %p", ext, id);
 
-	len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl);
-	pkt = malloc(len);
-	memset(pkt, 0, len);
-
-	ret = recv(data->sock, pkt, len, MSG_DONTWAIT);
-	if (ret <= 0)
-		return  -errno;
+	memset(buf, 0, sizeof(buf));
 
-	if(pkt->type != PKT_TYPE_CTL_NTFY) {
-		SNDERR("Unexpected packet type %d received!", pkt->type);
+	ret = recv(data->sock, ind, BT_AUDIO_IPC_PACKET_SIZE, MSG_DONTWAIT);
+	if (ind->h.msg_type > BT_MSG_MAX) {
+		SNDERR("Bogus message type %d "
+				"received from audio service",
+				ind->h.msg_type);
 		return -EAGAIN;
 	}
 
-	if(pkt->length != sizeof(struct ipc_data_ctl)) {
-		SNDERR("Unexpected packet length %d received", pkt->length);
+	if (ind->h.msg_type != BT_CONTROL_IND) {
+		SNDERR("Unexpected message %s received",
+				bt_audio_strmsg[ind->h.msg_type]);
 		return -EAGAIN;
 	}
 
-	ctl = (struct ipc_data_ctl *) pkt->data;
 	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
-	snd_ctl_elem_id_set_name(id, ctl->mode == BLUETOOTH_PLAYBACK ?
+	snd_ctl_elem_id_set_name(id, ind->mode == BLUETOOTH_PLAYBACK ?
 				vol_devices[BLUETOOTH_PLAYBACK] :
 				vol_devices[BLUETOOTH_CAPTURE]);
 	*event_mask = SND_CTL_EVENT_MASK_VALUE;
@@ -290,10 +285,7 @@ static snd_ctl_ext_callback_t bluetooth_callback = {
 
 static int bluetooth_init(struct bluetooth_data *data)
 {
-	int sk, err, id;
-	struct sockaddr_un addr = {
-		AF_UNIX, IPC_SOCKET_NAME
-	};
+	int sk;
 
 	if (!data)
 		return -EINVAL;
@@ -302,22 +294,10 @@ static int bluetooth_init(struct bluetooth_data *data)
 
 	data->sock = -1;
 
-	id = abs(getpid() * rand());
-
-	if ((sk = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
-		err = -errno;
-		SNDERR("Can't open socket");
+	if ((sk = bt_audio_service_open()) < 0) {
 		return -errno;
 	}
 
-	DBG("Connecting to address: %s", addr.sun_path + 1);
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		err = -errno;
-		SNDERR("Can't connect socket");
-		close(sk);
-		return err;
-	}
-
 	data->sock = sk;
 
 	return 0;
diff --git a/audio/device.c b/audio/device.c
index c86f711..a5b9b0a 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -450,7 +450,6 @@ static headset_state_t ipc_to_hs_state(uint8_t ipc_state)
 		return HEADSET_STATE_DISCONNECTED;
 	}
 }
-#endif
 
 static uint8_t avdtp_to_ipc_state(avdtp_state_t state)
 {
@@ -504,6 +503,7 @@ uint8_t device_get_state(struct device *dev)
 
 	return STATE_DISCONNECTED;
 }
+#endif
 
 gboolean device_is_connected(struct device *dev, const char *interface)
 {
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c
index e605158..56cece7 100644
--- a/audio/gsta2dpsink.c
+++ b/audio/gsta2dpsink.c
@@ -41,14 +41,6 @@
 
 #include "gsta2dpsink.h"
 
-enum {
-        NOT_CONFIGURED,
-        CONFIGURING_INIT,
-        CONFIGURING_SENT_CONF,
-        CONFIGURING_RCVD_DEV_CONF,
-        CONFIGURED
-};
-
 GST_DEBUG_CATEGORY_STATIC(a2dp_sink_debug);
 #define GST_CAT_DEFAULT a2dp_sink_debug
 
@@ -62,24 +54,10 @@ GST_DEBUG_CATEGORY_STATIC(a2dp_sink_debug);
 		g_mutex_unlock (s->sink_lock);		\
 	} G_STMT_END
 
-#define GST_A2DP_SINK_WAIT_CON_END(s) G_STMT_START {			\
-		s->waiting_con_conf = TRUE;				\
-		g_cond_wait (s->con_conf_end, s->sink_lock);		\
-		s->waiting_con_conf = FALSE;				\
-	} G_STMT_END
-
-#define GST_A2DP_SINK_CONFIGURATION_FAIL(s) G_STMT_START {		\
-		s->con_state = NOT_CONFIGURED;				\
-		g_cond_signal (s->con_conf_end);			\
-	} G_STMT_END
-
-#define GST_A2DP_SINK_CONFIGURATION_SUCCESS(s) G_STMT_START {		\
-		s->con_state = CONFIGURED;				\
-		g_cond_signal (s->con_conf_end);			\
-	} G_STMT_END
 
 struct bluetooth_data {
-	struct ipc_data_cfg cfg;	/* Bluetooth device config */
+	struct bt_getcapabilities_rsp cfg; /* Bluetooth device config */
+	gint link_mtu;
 	int samples;			/* Number of encoded samples */
 	gchar buffer[BUFFER_SIZE];	/* Codec transfer buffer */
 	gsize count;			/* Codec transfer buffer counter */
@@ -121,6 +99,13 @@ static GstStaticPadTemplate a2dp_sink_factory =
 				"rate = (int) { 16000, 22050, 24000, 32000, 44100, 48000 }, "
 				"channels = (int) [ 1, 2 ]"));
 
+static GIOError gst_a2dp_sink_audioservice_send(GstA2dpSink *self,
+					const bt_audio_msg_header_t *msg);
+static GIOError gst_a2dp_sink_audioservice_expect(GstA2dpSink *self,
+				bt_audio_msg_header_t *outmsg,
+				int expected_type);
+
+
 static void gst_a2dp_sink_base_init(gpointer g_class)
 {
 	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
@@ -137,8 +122,6 @@ static gboolean gst_a2dp_sink_stop(GstBaseSink *basesink)
 
 	GST_INFO_OBJECT(self, "stop");
 
-	self->con_state = NOT_CONFIGURED;
-
 	if (self->watch_id != 0) {
 		g_source_remove(self->watch_id);
 		self->watch_id = 0;
@@ -152,7 +135,7 @@ static gboolean gst_a2dp_sink_stop(GstBaseSink *basesink)
 	}
 
 	if (self->server) {
-		g_io_channel_close(self->server);
+		bt_audio_service_close(g_io_channel_unix_get_fd(self->server));
 		g_io_channel_unref(self->server);
 		self->server = NULL;
 	}
@@ -162,9 +145,9 @@ static gboolean gst_a2dp_sink_stop(GstBaseSink *basesink)
 		self->data = NULL;
 	}
 
-	if (self->sbc) {
-		g_free(self->sbc);
-		self->sbc = NULL;
+	if (self->stream_caps) {
+		gst_caps_unref(self->stream_caps);
+		self->stream_caps = NULL;
 	}
 
 	if (self->dev_caps) {
@@ -185,12 +168,6 @@ static void gst_a2dp_sink_finalize(GObject *object)
 	if (self->device)
 		g_free(self->device);
 
-	/* unlock any thread waiting for this signal */
-	GST_A2DP_SINK_MUTEX_LOCK(self);
-	GST_A2DP_SINK_CONFIGURATION_FAIL(self);
-	GST_A2DP_SINK_MUTEX_UNLOCK(self);
-
-	g_cond_free(self->con_conf_end);
 	g_mutex_free(self->sink_lock);
 
 	G_OBJECT_CLASS(parent_class)->finalize(object);
@@ -232,19 +209,10 @@ static void gst_a2dp_sink_get_property(GObject *object, guint prop_id,
 
 static gint gst_a2dp_sink_bluetooth_recvmsg_fd(GstA2dpSink *sink)
 {
-	char cmsg_b[CMSG_SPACE(sizeof(int))], m;
-	int err, ret, stream_fd;
-	struct iovec iov = { &m, sizeof(m) };
-	struct msghdr msgh;
-	struct cmsghdr *cmsg;
-
-	memset(&msgh, 0, sizeof(msgh));
-	msgh.msg_iov = &iov;
-	msgh.msg_iovlen = 1;
-	msgh.msg_control = &cmsg_b;
-	msgh.msg_controllen = CMSG_LEN(sizeof(int));
-
-	ret = recvmsg(g_io_channel_unix_get_fd(sink->server), &msgh, 0);
+	int err, ret;
+
+	ret = bt_audio_service_get_data_fd(g_io_channel_unix_get_fd(sink->server));
+
 	if (ret < 0) {
 		err = errno;
 		GST_ERROR_OBJECT(sink, "Unable to receive fd: %s (%d)",
@@ -252,76 +220,20 @@ static gint gst_a2dp_sink_bluetooth_recvmsg_fd(GstA2dpSink *sink)
 		return -err;
 	}
 
-	/* Receive auxiliary data in msgh */
-	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
-			cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
-		if (cmsg->cmsg_level == SOL_SOCKET
-				&& cmsg->cmsg_type == SCM_RIGHTS) {
-			stream_fd = (*(int *) CMSG_DATA(cmsg));
-			sink->stream = g_io_channel_unix_new(stream_fd);
-
-			GST_DEBUG_OBJECT(sink, "stream_fd=%d", stream_fd);
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static void gst_a2dp_sink_check_dev_caps(GstA2dpSink *self)
-{
-	GstStructure *structure;
-	GstCaps *dev_caps;
-	gint channels;
-
-	structure = gst_caps_get_structure(self->dev_caps, 0);
-	if (!gst_structure_get_int(structure, "channels", &channels))
-		channels = 2; /* FIXME how to get channels */
-	dev_caps = gst_sbc_caps_from_sbc(&(self->data->cfg), self->sbc,
-			channels);
-
-	self->new_dev_caps = TRUE;
-	gst_caps_unref(self->dev_caps);
-	self->dev_caps = gst_caps_ref(dev_caps);
-
-
-}
-
-static int gst_a2dp_sink_bluetooth_a2dp_init(GstA2dpSink *self,
-			struct ipc_codec_sbc *sbc)
-{
-	struct bluetooth_data *data = self->data;
-	struct ipc_data_cfg *cfg = &data->cfg;
-
-	if (cfg == NULL) {
-		GST_ERROR_OBJECT(self, "Error getting codec parameters");
-		return -1;
-	}
-
-	if (cfg->codec != CFG_CODEC_SBC)
-		return -1;
-
-	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
-
-	GST_DEBUG_OBJECT(self, "Codec parameters: "
-				"\tallocation=%u\n\tsubbands=%u\n "
-				"\tblocks=%u\n\tbitpool=%u\n",
-				sbc->allocation, sbc->subbands,
-				sbc->blocks, sbc->bitpool);
+	sink->stream = g_io_channel_unix_new(ret);
+	GST_DEBUG_OBJECT(sink, "stream_fd=%d", ret);
 
 	return 0;
 }
 
 static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink,
 					GstCaps *caps,
-					struct ipc_packet *pkt)
+					sbc_capabilities_t *pkt)
 {
-
-	struct ipc_data_cfg *cfg = (void *) pkt->data;
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
+	sbc_capabilities_t *cfg = &sink->data->cfg.sbc_capabilities;
 	const GValue *value = NULL;
 	const char *pref, *name;
-	GstStructure *structure = gst_caps_get_structure(caps,0);
+	GstStructure *structure = gst_caps_get_structure(caps, 0);
 
 	name = gst_structure_get_name(structure);
 	/* FIXME only sbc supported here, should suport mp3 */
@@ -330,26 +242,21 @@ static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink,
 		return FALSE;
 	}
 
-	if (sink->device)
-		strncpy(pkt->device, sink->device, 18);
-
-	pkt->role = PKT_ROLE_HIFI;
-
 	value = gst_structure_get_value(structure, "rate");
-	cfg->rate = g_value_get_int(value);
+	cfg->frequency = g_value_get_int(value);
 
 	value = gst_structure_get_value(structure, "mode");
 	pref = g_value_get_string(value);
 	if (strcmp(pref, "auto") == 0)
-		cfg->mode = CFG_MODE_AUTO;
+		cfg->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO;
 	else if (strcmp(pref, "mono") == 0)
-		cfg->mode = CFG_MODE_MONO;
+		cfg->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
 	else if (strcmp(pref, "dual") == 0)
-		cfg->mode = CFG_MODE_DUAL_CHANNEL;
+		cfg->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
 	else if (strcmp(pref, "stereo") == 0)
-		cfg->mode = CFG_MODE_STEREO;
+		cfg->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
 	else if (strcmp(pref, "joint") == 0)
-		cfg->mode = CFG_MODE_JOINT_STEREO;
+		cfg->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
 	else {
 		GST_ERROR_OBJECT(sink, "Invalid mode %s", pref);
 		return FALSE;
@@ -358,107 +265,27 @@ static gboolean gst_a2dp_sink_init_pkt_conf(GstA2dpSink *sink,
 	value = gst_structure_get_value(structure, "allocation");
 	pref = g_value_get_string(value);
 	if (strcmp(pref, "auto") == 0)
-		sbc->allocation = CFG_ALLOCATION_AUTO;
+		cfg->allocation_method = BT_A2DP_ALLOCATION_AUTO;
 	else if (strcmp(pref, "loudness") == 0)
-		sbc->allocation = CFG_ALLOCATION_LOUDNESS;
+		cfg->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
 	else if (strcmp(pref, "snr") == 0)
-		sbc->allocation = CFG_ALLOCATION_SNR;
+		cfg->allocation_method = BT_A2DP_ALLOCATION_SNR;
 	else {
 		GST_ERROR_OBJECT(sink, "Invalid allocation: %s", pref);
 		return FALSE;
 	}
 
 	value = gst_structure_get_value(structure, "subbands");
-	sbc->subbands = g_value_get_int(value);
+	cfg->subbands = g_value_get_int(value);
 
 	value = gst_structure_get_value(structure, "blocks");
-	sbc->blocks = g_value_get_int(value);
+	cfg->block_length = g_value_get_int(value);
 
+	/* FIXME min and max ??? */
 	value = gst_structure_get_value(structure, "bitpool");
-	sbc->bitpool = g_value_get_int(value);
-
-	pkt->length = sizeof(*cfg) + sizeof(*sbc);
-	pkt->type = PKT_TYPE_CFG_REQ;
-	pkt->error = PKT_ERROR_NONE;
-
-	return TRUE;
-}
-
-static gboolean gst_a2dp_sink_conf_resp(GstA2dpSink *sink)
-{
-	gchar buf[IPC_MTU];
-	GIOError io_error;
-	gsize ret;
-	gint total;
-	struct ipc_packet *pkt = (void *) buf;
-	struct ipc_data_cfg *cfg = (void *) pkt->data;
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
-
-	memset(buf, 0, sizeof(buf));
-
-	io_error = g_io_channel_read(sink->server, (gchar *) buf,
-			sizeof(*pkt) + sizeof(*cfg), &ret);
-	if (io_error != G_IO_ERROR_NONE && ret > 0) {
-		GST_ERROR_OBJECT(sink, "Error ocurred while receiving "
-					"configurarion packet answer");
-		return FALSE;
-	}
-
-	total = ret;
-	if (pkt->type != PKT_TYPE_CFG_RSP) {
-		GST_ERROR_OBJECT(sink, "Unexpected packet type %d "
-					"received", pkt->type);
-		return FALSE;
-	}
-
-	if (pkt->error != PKT_ERROR_NONE) {
-		GST_ERROR_OBJECT(sink, "Error %d while configuring "
-					"device", pkt->error);
-		return FALSE;
-	}
-
-	if (cfg->codec != CFG_CODEC_SBC) {
-		GST_ERROR_OBJECT(sink, "Unsupported format");
-		return FALSE;
-	}
-
-	io_error = g_io_channel_read(sink->server, (gchar *) sbc,
-					sizeof(*sbc), &ret);
-	if (io_error != G_IO_ERROR_NONE) {
-		GST_ERROR_OBJECT(sink, "Error while reading data from socket "
-				"%s (%d)", strerror(errno), errno);
-		return FALSE;
-	} else if (ret == 0) {
-		GST_ERROR_OBJECT(sink, "Read 0 bytes from socket");
-		return FALSE;
-	}
-
-	total += ret;
-	GST_DEBUG_OBJECT(sink, "OK - %d bytes received", total);
-
-	if (pkt->length != (total - sizeof(struct ipc_packet))) {
-		GST_ERROR_OBJECT(sink, "Error while configuring device: "
-			"packet size doesn't match");
-		return FALSE;
-	}
+	cfg->max_bitpool = cfg->min_bitpool = g_value_get_int(value);
 
-	memcpy(&sink->data->cfg, cfg, sizeof(*cfg));
-	memcpy(sink->sbc, sbc, sizeof(struct ipc_codec_sbc));
-
-	gst_a2dp_sink_check_dev_caps(sink);
-
-	GST_DEBUG_OBJECT(sink, "Device configuration:\n\tchannel=%p\n\t"
-			"fd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u",
-			sink->stream, sink->data->cfg.fd_opt,
-			sink->data->cfg.pkt_len, sink->data->cfg.sample_size,
-			sink->data->cfg.rate);
-
-	if (sink->data->cfg.codec == CFG_CODEC_SBC) {
-		/* FIXME is this necessary? */
-		ret = gst_a2dp_sink_bluetooth_a2dp_init(sink, sbc);
-		if (ret < 0)
-			return FALSE;
-	}
+	memcpy(pkt, cfg, sizeof(*pkt));
 
 	return TRUE;
 }
@@ -504,7 +331,7 @@ static gboolean gst_a2dp_sink_conf_recv_stream_fd(GstA2dpSink *self)
 	GST_LOG_OBJECT(self, "emptying stream pipe");
 	while (1) {
 		err = g_io_channel_read(self->stream, data->buffer,
-					(gsize) data->cfg.pkt_len,
+					(gsize) data->cfg.link_mtu,
 					&read);
 		if (err != G_IO_ERROR_NONE || read <= 0)
 			break;
@@ -531,33 +358,6 @@ static gboolean gst_a2dp_sink_conf_recv_stream_fd(GstA2dpSink *self)
 	return TRUE;
 }
 
-static void gst_a2dp_sink_conf_recv_data(GstA2dpSink *sink)
-{
-	/*
-	 * We hold the lock, since we can send a signal.
-	 * It is a good practice, according to the glib api.
-	 */
-	GST_A2DP_SINK_MUTEX_LOCK(sink);
-
-	switch (sink->con_state) {
-	case CONFIGURING_SENT_CONF:
-		if (gst_a2dp_sink_conf_resp(sink))
-			sink->con_state = CONFIGURING_RCVD_DEV_CONF;
-		else
-			GST_A2DP_SINK_CONFIGURATION_FAIL(sink);
-		break;
-	case CONFIGURING_RCVD_DEV_CONF:
-		if (gst_a2dp_sink_conf_recv_stream_fd(sink))
-			GST_A2DP_SINK_CONFIGURATION_SUCCESS(sink);
-		else
-			GST_A2DP_SINK_CONFIGURATION_FAIL(sink);
-		break;
-	}
-
-	GST_A2DP_SINK_MUTEX_UNLOCK(sink);
-}
-
-
 static gboolean server_callback(GIOChannel *chan,
 					GIOCondition cond, gpointer data)
 {
@@ -568,16 +368,217 @@ static gboolean server_callback(GIOChannel *chan,
 	else if (cond & G_IO_ERR) {
 		sink = GST_A2DP_SINK(data);
 		GST_WARNING_OBJECT(sink, "Untreated callback G_IO_ERR");
-	} else if (cond & G_IO_IN) {
-		sink = GST_A2DP_SINK(data);
-		if (sink->con_state != NOT_CONFIGURED &&
-			sink->con_state != CONFIGURED)
-			gst_a2dp_sink_conf_recv_data(sink);
-		else
-			GST_WARNING_OBJECT(sink, "Unexpected data received");
+	}
+
+	return TRUE;
+}
+
+static gboolean gst_a2dp_sink_update_caps(GstA2dpSink *self)
+{
+	sbc_capabilities_t *sbc = &self->data->cfg.sbc_capabilities;
+	GstStructure *structure;
+	GValue *value;
+	GValue *list;
+	gchar *tmp;
+
+	GST_LOG_OBJECT(self, "updating device caps");
+
+	structure = gst_structure_empty_new("audio/x-sbc");
+	value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
+
+	/* mode */
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->channel_mode == BT_A2DP_CHANNEL_MODE_AUTO) {
+		g_value_set_static_string(value, "joint");
+		gst_value_list_prepend_value(list, value);
+		g_value_set_static_string(value, "stereo");
+		gst_value_list_prepend_value(list, value);
+		g_value_set_static_string(value, "mono");
+		gst_value_list_prepend_value(list, value);
+		g_value_set_static_string(value, "dual");
+		gst_value_list_prepend_value(list, value);
 	} else {
-		sink = GST_A2DP_SINK(data);
-		GST_WARNING_OBJECT(sink, "Unexpected callback call");
+		if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
+			g_value_set_static_string(value, "mono");
+			gst_value_list_prepend_value(list, value);
+		}
+		if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) {
+			g_value_set_static_string(value, "stereo");
+			gst_value_list_prepend_value(list, value);
+		}
+		if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) {
+			g_value_set_static_string(value, "dual");
+			gst_value_list_prepend_value(list, value);
+		}
+		if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) {
+			g_value_set_static_string(value, "joint");
+			gst_value_list_prepend_value(list, value);
+		}
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "mode", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* subbands */
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	value = g_value_init(value, G_TYPE_INT);
+	if (sbc->subbands & BT_A2DP_SUBBANDS_4) {
+		g_value_set_int(value, 4);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->subbands & BT_A2DP_SUBBANDS_8) {
+		g_value_set_int(value, 8);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "subbands", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* blocks */
+	value = g_value_init(value, G_TYPE_INT);
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) {
+		g_value_set_int(value, 16);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) {
+		g_value_set_int(value, 12);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) {
+		g_value_set_int(value, 8);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) {
+		g_value_set_int(value, 4);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "blocks", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* allocation */
+	g_value_init(value, G_TYPE_STRING);
+	list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST);
+	if (sbc->allocation_method == BT_A2DP_ALLOCATION_AUTO) {
+		g_value_set_static_string(value, "loudness");
+		gst_value_list_prepend_value(list, value);
+		g_value_set_static_string(value, "snr");
+		gst_value_list_prepend_value(list, value);
+	} else {
+		if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) {
+			g_value_set_static_string(value, "loudness");
+			gst_value_list_prepend_value(list, value);
+		}
+		if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) {
+			g_value_set_static_string(value, "snr");
+			gst_value_list_prepend_value(list, value);
+		}
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "allocation", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* rate */
+	g_value_init(value, G_TYPE_INT);
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_48000) {
+		g_value_set_int(value, 48000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_44100) {
+		g_value_set_int(value, 44100);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_32000) {
+		g_value_set_int(value, 32000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_16000) {
+		g_value_set_int(value, 16000);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "rate", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* bitpool */
+	value = g_value_init(value, GST_TYPE_INT_RANGE);
+	gst_value_set_int_range(value, sbc->min_bitpool, sbc->max_bitpool);
+	gst_structure_set_value(structure, "bitpool", value);
+
+	/* channels */
+	gst_value_set_int_range(value, 1, 2);
+	gst_structure_set_value(structure, "channels", value);
+
+	g_free(value);
+
+	self->dev_caps = gst_caps_new_full(structure, NULL);
+
+	tmp = gst_caps_to_string(self->dev_caps);
+	GST_DEBUG_OBJECT(self, "Device capabilities: %s", tmp);
+	g_free(tmp);
+
+	return TRUE;
+}
+
+static gboolean gst_a2dp_sink_get_capabilities(GstA2dpSink *self)
+{
+	gchar *buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_getcapabilities_req *req = (void *) buf;
+	struct bt_getcapabilities_rsp *rsp = (void *) buf;
+	GIOError io_error;
+
+	memset(req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+
+	req->h.msg_type = BT_GETCAPABILITIES_REQ;
+	strncpy(req->device, self->device, 18);
+
+	req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+	req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
+	io_error = gst_a2dp_sink_audioservice_send(self, &req->h);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error while asking device caps");
+	}
+
+	io_error = gst_a2dp_sink_audioservice_expect(self, &rsp->h,
+			BT_GETCAPABILITIES_RSP);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error while getting device caps");
+		return FALSE;
+	}
+
+	if (rsp->posix_errno != 0) {
+		GST_ERROR_OBJECT(self, "BT_GETCAPABILITIES failed : %s(%d)",
+					strerror(rsp->posix_errno),
+					rsp->posix_errno);
+		return FALSE;
+	}
+
+	if (rsp->transport != BT_CAPABILITIES_TRANSPORT_A2DP) {
+		GST_ERROR_OBJECT(self, "Non a2dp answer from device");
+		return FALSE;
+	}
+
+	memcpy(&self->data->cfg, rsp, sizeof(*rsp));
+	if (!gst_a2dp_sink_update_caps(self)) {
+		GST_WARNING_OBJECT(self, "failed to update capabilities");
+		return FALSE;
 	}
 
 	return TRUE;
@@ -586,7 +587,6 @@ static gboolean server_callback(GIOChannel *chan,
 static gboolean gst_a2dp_sink_start(GstBaseSink *basesink)
 {
 	GstA2dpSink *self = GST_A2DP_SINK(basesink);
-	struct sockaddr_un addr = { AF_UNIX, IPC_SOCKET_NAME };
 	gint sk;
 	gint err;
 
@@ -594,107 +594,146 @@ static gboolean gst_a2dp_sink_start(GstBaseSink *basesink)
 
 	self->watch_id = 0;
 
-	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
-	if (sk < 0) {
-		err = errno;
-		GST_ERROR_OBJECT(self, "Cannot open socket: %s (%d)",
-			strerror(err), err);
-		return FALSE;
-	}
-
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+	sk = bt_audio_service_open();
+	if (sk <= 0) {
 		err = errno;
-		GST_ERROR_OBJECT(self, "Connection fail %s (%d)",
-			strerror(err), err);
-		close(sk);
-		return FALSE;
+		GST_ERROR_OBJECT(self, "Cannot open connection to bt "
+			"audio service: %s %d", strerror(err), err);
+		goto failed;
 	}
 
 	self->server = g_io_channel_unix_new(sk);
-
-	self->watch_id = g_io_add_watch(self->server, G_IO_IN | G_IO_HUP |
-			G_IO_ERR | G_IO_NVAL, server_callback, self);
+	self->watch_id = g_io_add_watch(self->server, G_IO_HUP | G_IO_ERR |
+					G_IO_NVAL, server_callback, self);
 
 	self->data = g_new0(struct bluetooth_data, 1);
 	memset(self->data, 0, sizeof(struct bluetooth_data));
 
-	self->sbc = g_new0(struct ipc_codec_sbc, 1);
-
 	self->stream = NULL;
-	self->con_state = NOT_CONFIGURED;
-	self->new_dev_caps = FALSE;
-	self->dev_caps = NULL;
+	self->stream_caps = NULL;
 
-	self->waiting_con_conf = FALSE;
+	if (!gst_a2dp_sink_get_capabilities(self))
+		goto failed;
 
 	return TRUE;
+
+failed:
+	bt_audio_service_close(sk);
+	return FALSE;
 }
 
-static gboolean gst_a2dp_sink_send_conf_pkt(GstA2dpSink *sink, GstCaps *caps)
+static gboolean gst_a2dp_sink_stream_start(GstA2dpSink *self)
 {
-	gchar buf[IPC_MTU];
-	struct ipc_packet *pkt = (void *) buf;
-	gboolean ret;
-	gsize bytes_sent;
+	gchar buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_streamstart_req *req = (void *) buf;
+	struct bt_streamstart_rsp *rsp = (void *) buf;
+	struct bt_datafd_ind *ind = (void*) buf;
 	GIOError io_error;
 
-	g_assert(sink->con_state == NOT_CONFIGURED);
+	GST_DEBUG_OBJECT(self, "stream start");
 
-	memset (pkt, 0, sizeof(buf));
-	ret = gst_a2dp_sink_init_pkt_conf(sink, caps, pkt);
-	if (!ret) {
-		GST_ERROR_OBJECT(sink, "Couldn't initialize parse caps "
-				"to packet configuration");
+	memset (req, 0, sizeof(buf));
+	req->h.msg_type = BT_STREAMSTART_REQ;
+
+	io_error = gst_a2dp_sink_audioservice_send(self, &req->h);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error ocurred while sending "
+					"start packet");
 		return FALSE;
 	}
 
-	sink->con_state = CONFIGURING_INIT;
+	GST_DEBUG_OBJECT(self, "stream start packet sent");
 
-	io_error = g_io_channel_write(sink->server, (gchar *) pkt,
-			sizeof(*pkt) + pkt->length, &bytes_sent);
+	io_error = gst_a2dp_sink_audioservice_expect(self, &rsp->h,
+			BT_STREAMSTART_RSP);
 	if (io_error != G_IO_ERROR_NONE) {
-		GST_ERROR_OBJECT(sink, "Error ocurred while sending "
-					"configurarion packet");
-		sink->con_state = NOT_CONFIGURED;
+		GST_ERROR_OBJECT(self, "Error while stream start confirmation");
+		return FALSE;
+	}
+
+	if (rsp->posix_errno != 0) {
+		GST_ERROR_OBJECT(self, "BT_STREAMSTART_RSP failed : %s(%d)",
+					strerror(rsp->posix_errno),
+					rsp->posix_errno);
 		return FALSE;
 	}
 
-	GST_DEBUG_OBJECT(sink, "%d bytes sent", bytes_sent);
-	sink->con_state = CONFIGURING_SENT_CONF;
+	GST_DEBUG_OBJECT(self, "stream started");
+
+	io_error = gst_a2dp_sink_audioservice_expect(self, &ind->h,
+			BT_STREAMFD_IND);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error while receiving stream filedescriptor");
+		return FALSE;
+	}
+
+	if (!gst_a2dp_sink_conf_recv_stream_fd(self))
+		return FALSE;
 
 	return TRUE;
 }
 
-static gboolean gst_a2dp_sink_start_dev_conf(GstA2dpSink *sink, GstCaps *caps)
+static gboolean gst_a2dp_sink_configure(GstA2dpSink *self, GstCaps *caps)
 {
+	gchar buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_setconfiguration_req *req = (void *) buf;
+	struct bt_setconfiguration_rsp *rsp = (void *) buf;
 	gboolean ret;
+	GIOError io_error;
 
-	g_assert(sink->con_state == NOT_CONFIGURED);
+	GST_DEBUG_OBJECT(self, "configuring device");
 
-	GST_DEBUG_OBJECT(sink, "starting device configuration");
+	memset (req, 0, sizeof(buf));
+	req->h.msg_type = BT_SETCONFIGURATION_REQ;
+	strncpy(req->device, self->device, 18);
+	ret = gst_a2dp_sink_init_pkt_conf(self, caps, &req->sbc_capabilities);
+	if (!ret) {
+		GST_ERROR_OBJECT(self, "Couldn't parse caps "
+				"to packet configuration");
+		return FALSE;
+	}
+
+	io_error = gst_a2dp_sink_audioservice_send(self, &req->h);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error ocurred while sending "
+					"configurarion packet");
+		return FALSE;
+	}
 
-	ret = gst_a2dp_sink_send_conf_pkt(sink, caps);
+	GST_DEBUG_OBJECT(self, "configuration packet sent");
 
-	return ret;
+	io_error = gst_a2dp_sink_audioservice_expect(self, &rsp->h,
+			BT_SETCONFIGURATION_RSP);
+	if (io_error != G_IO_ERROR_NONE) {
+		GST_ERROR_OBJECT(self, "Error while receiving device confirmation");
+		return FALSE;
+	}
+
+	if (rsp->posix_errno != 0) {
+		GST_ERROR_OBJECT(self, "BT_SETCONFIGURATION_RSP failed : %s(%d)",
+					strerror(rsp->posix_errno),
+					rsp->posix_errno);
+		return FALSE;
+	}
+
+	GST_DEBUG_OBJECT(self, "configuration set");
+
+	return TRUE;
 }
 
 static GstFlowReturn gst_a2dp_sink_preroll(GstBaseSink *basesink,
 					GstBuffer *buffer)
 {
 	GstA2dpSink *sink = GST_A2DP_SINK(basesink);
+	gboolean ret;
 
 	GST_A2DP_SINK_MUTEX_LOCK(sink);
 
-	if (sink->con_state == NOT_CONFIGURED)
-		gst_a2dp_sink_start_dev_conf(sink, GST_BUFFER_CAPS(buffer));
-
-	/* wait for the connection process to finish */
-	if (sink->con_state != CONFIGURED)
-		GST_A2DP_SINK_WAIT_CON_END(sink);
+	ret = gst_a2dp_sink_stream_start(sink);
 
 	GST_A2DP_SINK_MUTEX_UNLOCK(sink);
 
-	if (sink->con_state != CONFIGURED)
+	if (!ret)
 		return GST_FLOW_ERROR;
 
 	return GST_FLOW_OK;
@@ -745,7 +784,7 @@ static GstFlowReturn gst_a2dp_sink_render(GstBaseSink *basesink,
 
 	encoded = GST_BUFFER_SIZE(buffer);
 
-	if (data->count + encoded >= data->cfg.pkt_len) {
+	if (data->count + encoded >= data->cfg.link_mtu) {
 		ret = gst_a2dp_sink_avdtp_write(self);
 		if (ret < 0)
 			return GST_FLOW_ERROR;
@@ -758,24 +797,28 @@ static GstFlowReturn gst_a2dp_sink_render(GstBaseSink *basesink,
 	return GST_FLOW_OK;
 }
 
+static GstCaps* gst_a2dp_sink_get_caps(GstBaseSink *basesink)
+{
+	GstA2dpSink *self = GST_A2DP_SINK(basesink);
+
+	return self->dev_caps ? gst_caps_ref(self->dev_caps): NULL;/*FIXME use template caps*/
+}
+
 static gboolean gst_a2dp_sink_set_caps(GstBaseSink *basesink, GstCaps *caps)
 {
 	GstA2dpSink *self = GST_A2DP_SINK(basesink);
+	gboolean ret;
 
 	GST_A2DP_SINK_MUTEX_LOCK(self);
-	if (self->con_state == NOT_CONFIGURED) {
-		gst_a2dp_sink_start_dev_conf(self, caps);
+	ret = gst_a2dp_sink_configure(self, caps);
 
-		if (self->dev_caps)
-			gst_caps_unref(self->dev_caps);
-		self->dev_caps = gst_caps_ref(caps);
+	if (self->stream_caps)
+		gst_caps_unref(self->stream_caps);
+	self->stream_caps = gst_caps_ref(caps);
 
-		/* we suppose the device will accept this caps */
-		self->new_dev_caps = FALSE;
-	}
 	GST_A2DP_SINK_MUTEX_UNLOCK(self);
 
-	return TRUE;
+	return ret;
 }
 
 static gboolean gst_a2dp_sink_unlock(GstBaseSink *basesink)
@@ -800,12 +843,7 @@ static GstFlowReturn gst_a2dp_sink_buffer_alloc(GstBaseSink *basesink,
 		return GST_FLOW_ERROR;
 	}
 
-	if (self->new_dev_caps && self->dev_caps) {
-		GST_INFO_OBJECT(self, "new caps from device");
-		gst_buffer_set_caps(*buf, self->dev_caps);
-		self->new_dev_caps = FALSE;
-	} else
-		gst_buffer_set_caps(*buf, caps);
+	gst_buffer_set_caps(*buf, caps);
 
 	GST_BUFFER_OFFSET(*buf) = offset;
 
@@ -830,6 +868,7 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass)
 	basesink_class->render = GST_DEBUG_FUNCPTR(gst_a2dp_sink_render);
 	basesink_class->preroll = GST_DEBUG_FUNCPTR(gst_a2dp_sink_preroll);
 	basesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_caps);
+	basesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_a2dp_sink_get_caps);
 	basesink_class->unlock = GST_DEBUG_FUNCPTR(gst_a2dp_sink_unlock);
 	basesink_class->buffer_alloc =
 		GST_DEBUG_FUNCPTR(gst_a2dp_sink_buffer_alloc);
@@ -847,12 +886,74 @@ static void gst_a2dp_sink_init(GstA2dpSink *self, GstA2dpSinkClass *klass)
 {
 	self->device = NULL;
 	self->data = NULL;
-	self->sbc = NULL;
 
 	self->stream = NULL;
-	self->con_state = NOT_CONFIGURED;
 
-	self->con_conf_end = g_cond_new();
-	self->waiting_con_conf = FALSE;
+	self->dev_caps = NULL;
+
 	self->sink_lock = g_mutex_new();
 }
+
+static GIOError gst_a2dp_sink_audioservice_send(GstA2dpSink *self,
+					const bt_audio_msg_header_t *msg)
+{
+	gint err;
+	GIOError error;
+	gsize written;
+
+	GST_DEBUG_OBJECT(self, "sending %s", bt_audio_strmsg[msg->msg_type]);
+
+	error = g_io_channel_write(self->server, (const gchar*) msg,
+			BT_AUDIO_IPC_PACKET_SIZE, &written);
+	if (error == G_IO_ERROR_NONE) {
+		err = 0;
+	} else {
+		err = -errno;
+		GST_ERROR_OBJECT(self, "Error sending data to audio service:"
+			" %s(%d)", strerror(errno), errno);
+	}
+	return error;
+}
+
+static GIOError gst_a2dp_sink_audioservice_recv(GstA2dpSink *self,
+					bt_audio_msg_header_t *inmsg)
+{
+	GIOError status;
+	gsize bytes_read;
+
+	status = g_io_channel_read(self->server, (gchar*) inmsg,
+			BT_AUDIO_IPC_PACKET_SIZE, &bytes_read);
+	if (status == G_IO_ERROR_NONE) {
+		if (inmsg->msg_type <= BT_MSG_MAX) {
+			GST_DEBUG_OBJECT(self, "Received %s",
+					bt_audio_strmsg[inmsg->msg_type]);
+		} else {
+			status = G_IO_ERROR_INVAL;
+			GST_ERROR_OBJECT(self, "Bogus message type %d "
+					"received from audio service",
+					inmsg->msg_type);
+		}
+	} else
+		GST_ERROR_OBJECT(self, "Error receiving data from audio service");
+
+	return status;
+}
+
+static GIOError gst_a2dp_sink_audioservice_expect(GstA2dpSink *self, bt_audio_msg_header_t *outmsg,
+				int expected_type)
+{
+	GIOError status;
+
+	status = gst_a2dp_sink_audioservice_recv(self, outmsg);
+	if (status == G_IO_ERROR_NONE) {
+		if (outmsg->msg_type != expected_type) {
+			GST_ERROR_OBJECT(self, "Bogus message %s "
+					"received while %s was expected",
+					bt_audio_strmsg[outmsg->msg_type],
+					bt_audio_strmsg[expected_type]);
+			return G_IO_ERROR_INVAL;
+		}
+	}
+	return status;
+}
+
diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h
index ea75040..f5b9b69 100644
--- a/audio/gsta2dpsink.h
+++ b/audio/gsta2dpsink.h
@@ -49,15 +49,13 @@ struct _GstA2dpSink {
 	GIOChannel *stream;
 
 	struct bluetooth_data *data;
-	struct ipc_codec_sbc *sbc;
 	GIOChannel *server;
 
-	gint con_state;
+	/* stream connection data */
+	GstCaps *stream_caps;
+
 	GstCaps *dev_caps;
-	gboolean new_dev_caps;
 
-	GCond *con_conf_end;
-	gboolean waiting_con_conf;
 	GMutex *sink_lock;
 
 	guint watch_id;
diff --git a/audio/gstsbcenc.c b/audio/gstsbcenc.c
index 54bb7f8..333b327 100644
--- a/audio/gstsbcenc.c
+++ b/audio/gstsbcenc.c
@@ -27,14 +27,17 @@
 
 #include <string.h>
 
+#include "ipc.h"
 #include "gstsbcenc.h"
 #include "gstsbcutil.h"
 
-#define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO
-#define SBC_ENC_DEFAULT_BLOCKS 16
-#define SBC_ENC_DEFAULT_SUB_BANDS 8
-#define SBC_ENC_DEFAULT_BITPOOL 53
-#define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO
+#define SBC_ENC_DEFAULT_MODE BT_A2DP_CHANNEL_MODE_AUTO
+#define SBC_ENC_DEFAULT_BLOCKS 0
+#define SBC_ENC_DEFAULT_SUB_BANDS 0
+#define SBC_ENC_DEFAULT_BITPOOL 0
+#define SBC_ENC_DEFAULT_ALLOCATION BT_A2DP_ALLOCATION_AUTO
+#define SBC_ENC_DEFAULT_RATE 0
+#define SBC_ENC_DEFAULT_CHANNELS 0
 
 GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);
 #define GST_CAT_DEFAULT sbc_enc_debug
@@ -65,9 +68,9 @@ static GType gst_sbc_allocation_get_type(void)
 {
 	static GType sbc_allocation_type = 0;
 	static GEnumValue sbc_allocations[] = {
-		{ CFG_ALLOCATION_AUTO,		"Auto",		"auto" },
-		{ CFG_ALLOCATION_LOUDNESS,	"Loudness",	"loudness" },
-		{ CFG_ALLOCATION_SNR,		"SNR",		"snr" },
+		{ BT_A2DP_ALLOCATION_AUTO,	"Auto",		"auto" },
+		{ BT_A2DP_ALLOCATION_LOUDNESS,	"Loudness",	"loudness" },
+		{ BT_A2DP_ALLOCATION_SNR,	"SNR",		"snr" },
 		{ -1, NULL, NULL}
 	};
 
@@ -115,73 +118,193 @@ static GstStaticPadTemplate sbc_enc_src_factory =
 				"allocation = (string) { snr, loudness },"
 				"bitpool = (int) [ 2, 64 ]"));
 
-static GstCaps* sbc_enc_generate_srcpad_caps(GstSbcEnc *enc, GstCaps *caps)
+gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps);
+
+static void sbc_enc_set_structure_int_param(GstSbcEnc *enc,
+			GstStructure *structure, const gchar* field,
+			gint field_value)
+{
+	GValue *value;
+
+	value = g_new0(GValue,1);
+	value = g_value_init(value, G_TYPE_INT);
+	g_value_set_int(value, field_value);
+	gst_structure_set_value(structure, field, value);
+	g_free(value);
+}
+
+static void sbc_enc_set_structure_string_param(GstSbcEnc *enc,
+			GstStructure *structure, const gchar* field,
+			const gchar* field_value)
+{
+	GValue *value;
+
+	value = g_new0(GValue,1);
+	value = g_value_init(value, G_TYPE_STRING);
+	g_value_set_string(value, field_value);
+	gst_structure_set_value(structure, field, value);
+	g_free(value);
+}
+
+static GstCaps* sbc_enc_generate_srcpad_caps(GstSbcEnc *enc)
 {
-	gint rate;
-	gint channels;
 	GstCaps* src_caps;
 	GstStructure *structure;
-	const gchar *mode;
-	const gchar *allocation;
+	GEnumValue *enum_value;
+	GEnumClass *enum_class;
+	gchar* temp;
+
+	src_caps = gst_caps_copy(gst_pad_get_pad_template_caps(enc->srcpad));
+	structure = gst_caps_get_structure(src_caps, 0);
+
+	if (enc->rate != 0)
+		sbc_enc_set_structure_int_param(enc, structure, "rate",
+			enc->rate);
+
+	if (enc->channels != 0)
+		sbc_enc_set_structure_int_param(enc, structure, "channels",
+			enc->channels);
+
+	if (enc->subbands != 0)
+		sbc_enc_set_structure_int_param(enc, structure, "subbands",
+			enc->subbands);
+
+	if (enc->blocks != 0)
+		sbc_enc_set_structure_int_param(enc, structure, "blocks",
+			enc->blocks);
+
+	if (enc->mode != BT_A2DP_CHANNEL_MODE_AUTO) {
+		enum_class = g_type_class_ref(GST_TYPE_SBC_MODE);
+		enum_value = g_enum_get_value(enum_class, enc->mode);
+		sbc_enc_set_structure_string_param(enc, structure, "mode",
+			enum_value->value_nick);
+		g_type_class_unref(enum_class);
+	}
 
-	structure = gst_caps_get_structure(caps, 0);
+	if (enc->allocation != BT_A2DP_ALLOCATION_AUTO) {
+		enum_class = g_type_class_ref(GST_TYPE_SBC_ALLOCATION);
+		enum_value = g_enum_get_value(enum_class, enc->allocation);
+		sbc_enc_set_structure_string_param(enc, structure, "allocation",
+			enum_value->value_nick);
+		g_type_class_unref(enum_class);
+	}
 
-	if (!gst_structure_get_int (structure, "rate", &rate))
-		return NULL;
-	if (!gst_structure_get_int (structure, "channels", &channels))
+	temp = gst_caps_to_string(src_caps);
+	GST_DEBUG_OBJECT(enc, "Srcpad caps: %s", temp);
+	g_free(temp);
+
+	return src_caps;
+}
+
+static GstCaps* sbc_enc_src_getcaps (GstPad * pad)
+{
+	GstSbcEnc *enc;
+
+	enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
+
+	return sbc_enc_generate_srcpad_caps(enc);
+}
+
+static gboolean sbc_enc_src_setcaps (GstPad *pad, GstCaps *caps)
+{
+	GstCaps* srcpad_caps;
+	GstCaps* temp_caps;
+	gboolean res = TRUE;
+	GstSbcEnc *enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
+
+	GST_LOG_OBJECT(enc, "setting srcpad caps");
+
+	srcpad_caps = sbc_enc_generate_srcpad_caps(enc);
+	temp_caps = gst_caps_intersect(srcpad_caps, caps);
+	if (temp_caps == GST_CAPS_NONE)
+		res = FALSE;
+
+	gst_caps_unref(temp_caps);
+	gst_caps_unref(srcpad_caps);
+
+	g_return_val_if_fail(res, FALSE);
+
+	return gst_sbc_enc_fill_sbc_params(enc, caps);
+}
+
+static GstCaps* sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps)
+{
+
+	gchar *error_message = NULL;
+	GstCaps* result;
+	
+	result = gst_sbc_util_caps_fixate(caps, &error_message);
+
+	if (!result) {
+		GST_ERROR_OBJECT (enc, "Invalid input caps caused parsing "
+				"error: %s", error_message);
+		g_free(error_message);
 		return NULL;
+	}
+
+	return result;
+}
 
-	enc->sbc.rate = rate;
-	enc->sbc.channels = channels;
+static GstCaps* sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc)
+{
+	GstCaps *peer_caps;
+	GstCaps *src_caps;
+	GstCaps *caps;
+	gboolean res = TRUE;
+	GstCaps *result_caps = NULL;
+
+	peer_caps = gst_pad_peer_get_caps(enc->srcpad);
+	if (!peer_caps)
+		return NULL;
 
-	if (enc->mode == CFG_MODE_AUTO)
-		enc->mode = CFG_MODE_JOINT_STEREO;
+	src_caps = sbc_enc_generate_srcpad_caps(enc);
+	caps = gst_caps_intersect(src_caps, peer_caps);
 
-	if (enc->mode == CFG_MODE_MONO || enc->mode == CFG_MODE_JOINT_STEREO)
-		enc->sbc.joint = 1;
+	if (caps == GST_CAPS_NONE || gst_caps_is_empty(caps)) {
+		res = FALSE;
+		goto done;
+	}
 
-	enc->sbc.blocks = enc->blocks;
-	enc->sbc.subbands = enc->subbands;
-	if (enc->allocation == 0)
-		enc->sbc.allocation = CFG_ALLOCATION_LOUDNESS;
-	else
-		enc->sbc.allocation = enc->allocation;
+	result_caps = sbc_enc_src_caps_fixate(enc, caps);
 
-	enc->sbc.bitpool = SBC_ENC_DEFAULT_BITPOOL;
+done:
 
-	mode = gst_sbc_get_mode_string(enc->sbc.joint);
-	allocation = gst_sbc_get_allocation_string(enc->sbc.allocation);
+	gst_caps_unref(src_caps);
+	gst_caps_unref(peer_caps);
+	gst_caps_unref(caps);
 
-	src_caps = gst_caps_new_simple("audio/x-sbc",
-					"rate", G_TYPE_INT, enc->sbc.rate,
-					"channels", G_TYPE_INT, enc->sbc.channels,
-					"mode", G_TYPE_STRING, mode,
-					"subbands", G_TYPE_INT, enc->sbc.subbands,
-					"blocks", G_TYPE_INT, enc->sbc.blocks,
-					"allocation", G_TYPE_STRING, allocation,
-					"bitpool", G_TYPE_INT, enc->sbc.bitpool,
-					NULL);
+	if (!res)
+		return NULL;
 
-	return src_caps;
+	return result_caps;
 }
 
 static gboolean sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
 {
 	GstSbcEnc *enc;
 	GstStructure *structure;
-	GstCaps *othercaps;
+	GstCaps *src_caps;
+	gint rate, channels;
+	gboolean res;
 
 	enc = GST_SBC_ENC(GST_PAD_PARENT (pad));
 	structure = gst_caps_get_structure(caps, 0);
 
-	othercaps = sbc_enc_generate_srcpad_caps(enc, caps);
-	if (othercaps == NULL)
+	if (!gst_structure_get_int(structure, "rate", &rate))
+		goto error;
+	if (!gst_structure_get_int(structure, "channels", &channels))
 		goto error;
 
-	gst_pad_set_caps (enc->srcpad, othercaps);
-	gst_caps_unref(othercaps);
+	enc->rate = rate;
+	enc->channels = channels;
 
-	return TRUE;
+	src_caps = sbc_enc_get_fixed_srcpad_caps(enc);
+	if (!src_caps)
+		goto error;
+	res = gst_pad_set_caps(enc->srcpad, src_caps);
+	gst_caps_unref(src_caps);
+
+	return res;
 
 error:
 	GST_ERROR_OBJECT (enc, "invalid input caps");
@@ -215,14 +338,13 @@ gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps)
 	if (!(allocation = gst_structure_get_string(structure, "allocation")))
 		return FALSE;
 
-	sbc_reinit(&enc->sbc, 0);
-	enc->sbc.rate = rate;
-	enc->sbc.channels = channels;
-	enc->blocks = blocks;
-	enc->sbc.subbands = subbands;
+	enc->rate = enc->sbc.rate = rate;
+	enc->channels = enc->sbc.channels = channels;
+	enc->blocks = enc->sbc.blocks = blocks;
+	enc->subbands = enc->sbc.subbands = subbands;
 	enc->sbc.bitpool = bitpool;
-	enc->mode = gst_sbc_get_mode_int(mode);
-	enc->allocation = gst_sbc_get_allocation_mode_int(allocation);
+	enc->mode = enc->sbc.joint = gst_sbc_get_mode_int(mode);
+	enc->allocation = enc->sbc.allocation = gst_sbc_get_allocation_mode_int(allocation);
 
 	return TRUE;
 }
@@ -292,7 +414,6 @@ static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer)
 
 		res = gst_pad_push(enc->srcpad, output);
 		if (res != GST_FLOW_OK) {
-			GST_ERROR_OBJECT(enc, "pad pushing failed");
 			goto done;
 		}
 
@@ -350,12 +471,30 @@ static void gst_sbc_enc_base_init(gpointer g_class)
 	gst_element_class_set_details(element_class, &sbc_enc_details);
 }
 
+static gboolean sbc_enc_set_blocks(GstSbcEnc *enc, gint value)
+{
+	if (value != 4 && value != 8 && value != 12 &&
+			value != 16 && value != 0)
+		return FALSE;
+	enc->blocks = value;
+	return TRUE;
+}
+
+static gboolean sbc_enc_set_subbands(GstSbcEnc *enc, gint value)
+{
+	if (value != 4 && value != 8 && value != 0)
+		return FALSE;
+	enc->subbands = value;
+	return TRUE;
+}
+
 static void gst_sbc_enc_set_property(GObject *object, guint prop_id,
 					const GValue *value, GParamSpec *pspec)
 {
 	GstSbcEnc *enc = GST_SBC_ENC(object);
 
-	/* TODO - CAN ONLY BE CHANGED ON READY AND BELOW */
+	/* changes to those properties will only happen on the next caps
+	 * negotiation */
 
 	switch (prop_id) {
 	case PROP_MODE:
@@ -365,12 +504,14 @@ static void gst_sbc_enc_set_property(GObject *object, guint prop_id,
 		enc->allocation = g_value_get_enum(value);
 		break;
 	case PROP_BLOCKS:
-		/* TODO - verify consistency */
-		enc->blocks = g_value_get_int(value);
+		if (!sbc_enc_set_blocks(enc, g_value_get_int(value)))
+			GST_WARNING_OBJECT(enc, "invalid value %d for "
+				"blocks property", g_value_get_int(value));
 		break;
 	case PROP_SUBBANDS:
-		/* TODO - verify consistency */
-		enc->subbands = g_value_get_int(value);
+		if (!sbc_enc_set_subbands(enc, g_value_get_int(value)))
+			GST_WARNING_OBJECT(enc, "invalid value %d for "
+				"subbands property", g_value_get_int(value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -428,7 +569,7 @@ static void gst_sbc_enc_class_init(GstSbcEncClass *klass)
 	g_object_class_install_property(object_class, PROP_BLOCKS,
 			g_param_spec_int("blocks", "Blocks",
 				"Blocks", 0, G_MAXINT,
-				SBC_ENC_DEFAULT_BLOCKS,	G_PARAM_READWRITE));
+				SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE));
 
 	g_object_class_install_property(object_class, PROP_SUBBANDS,
 			g_param_spec_int("subbands", "Sub Bands",
@@ -447,13 +588,18 @@ static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)
 	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
 
 	self->srcpad = gst_pad_new_from_static_template(&sbc_enc_src_factory, "src");
-	gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(sbc_enc_chain));
+	gst_pad_set_getcaps_function(self->srcpad, GST_DEBUG_FUNCPTR(sbc_enc_src_getcaps));
+	gst_pad_set_setcaps_function(self->srcpad, GST_DEBUG_FUNCPTR(sbc_enc_src_setcaps));
 	gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
 
+	gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(sbc_enc_chain));
+
 	self->subbands = SBC_ENC_DEFAULT_SUB_BANDS;
 	self->blocks = SBC_ENC_DEFAULT_BLOCKS;
 	self->mode = SBC_ENC_DEFAULT_MODE;
 	self->allocation = SBC_ENC_DEFAULT_ALLOCATION;
+	self->rate = SBC_ENC_DEFAULT_RATE;
+	self->channels = SBC_ENC_DEFAULT_CHANNELS;
 
 	self->adapter = gst_adapter_new();
 }
diff --git a/audio/gstsbcenc.h b/audio/gstsbcenc.h
index c5fc6bc..f65bcc9 100644
--- a/audio/gstsbcenc.h
+++ b/audio/gstsbcenc.h
@@ -25,8 +25,6 @@
 #include <gst/base/gstadapter.h>
 
 #include "sbc.h"
-#include "ipc.h"
-
 
 G_BEGIN_DECLS
 
@@ -51,6 +49,8 @@ struct _GstSbcEnc {
 	GstPad *srcpad;
 	GstAdapter *adapter;
 
+	gint rate;
+	gint channels;
 	gint mode;
 	gint blocks;
 	gint allocation;
diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c
index 185cda0..0e25c35 100644
--- a/audio/gstsbcparse.c
+++ b/audio/gstsbcparse.c
@@ -57,6 +57,7 @@ static GstStaticPadTemplate sbc_parse_src_factory =
 				"bitpool = (int) [ 2, 64 ]"));
 
 /* Creates a fixed caps from the caps given. */
+/* FIXME use gstsbcutil caps fixating function */
 static GstCaps* sbc_parse_select_caps(GstSbcParse *parse, GstCaps *caps)
 {
 	GstCaps *result;
@@ -67,6 +68,11 @@ static GstCaps* sbc_parse_select_caps(GstSbcParse *parse, GstCaps *caps)
 	const gchar* allocation = NULL;
 	const gchar* mode = NULL;
 	const gchar* error_message = NULL;
+	gchar* str;
+
+	str = gst_caps_to_string(caps);
+	GST_DEBUG_OBJECT(parse, "Parsing caps: %s", str);
+	g_free(str);
 
 	structure = gst_caps_get_structure(caps, 0);
 
@@ -205,9 +211,15 @@ static gboolean sbc_parse_sink_setcaps(GstPad * pad, GstCaps * caps)
 		other = gst_caps_new_any();
 
 	inter = gst_caps_intersect(caps, other);
+	if (gst_caps_is_empty(inter)) {
+		gst_caps_unref(inter);
+		return FALSE;
+	}
 	srccaps = sbc_parse_select_caps(parse, inter);
-	if (srccaps == NULL)
+	if (srccaps == NULL) {
+		gst_caps_unref(inter);
 		return FALSE;
+	}
 
 	gst_pad_set_caps(parse->srcpad, srccaps);
 
diff --git a/audio/gstsbcutil.c b/audio/gstsbcutil.c
index 1d7a122..58dda52 100644
--- a/audio/gstsbcutil.c
+++ b/audio/gstsbcutil.c
@@ -99,11 +99,11 @@ const gchar *gst_sbc_get_mode_from_list(const GValue *value)
 gint gst_sbc_get_allocation_mode_int(const gchar *allocation)
 {
 	if (g_ascii_strcasecmp(allocation, "loudness") == 0)
-		return CFG_ALLOCATION_LOUDNESS;
+		return BT_A2DP_ALLOCATION_LOUDNESS;
 	else if (g_ascii_strcasecmp(allocation, "snr") == 0)
-		return CFG_ALLOCATION_SNR;
+		return BT_A2DP_ALLOCATION_SNR;
 	else if (g_ascii_strcasecmp(allocation, "auto") == 0)
-		return CFG_ALLOCATION_AUTO;
+		return BT_A2DP_ALLOCATION_AUTO;
 	else
 		return -1;
 }
@@ -111,15 +111,15 @@ gint gst_sbc_get_allocation_mode_int(const gchar *allocation)
 gint gst_sbc_get_mode_int(const gchar *mode)
 {
 	if (g_ascii_strcasecmp(mode, "joint") == 0)
-		return CFG_MODE_JOINT_STEREO;
+		return BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
 	else if (g_ascii_strcasecmp(mode, "stereo") == 0)
-		return CFG_MODE_STEREO;
+		return BT_A2DP_CHANNEL_MODE_STEREO;
 	else if (g_ascii_strcasecmp(mode, "dual") == 0)
-		return CFG_MODE_DUAL_CHANNEL;
+		return BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
 	else if (g_ascii_strcasecmp(mode, "mono") == 0)
-		return CFG_MODE_MONO;
+		return BT_A2DP_CHANNEL_MODE_MONO;
 	else if (g_ascii_strcasecmp(mode, "auto") == 0)
-		return CFG_MODE_AUTO;
+		return BT_A2DP_CHANNEL_MODE_AUTO;
 	else
 		return -1;
 }
@@ -127,15 +127,15 @@ gint gst_sbc_get_mode_int(const gchar *mode)
 const gchar *gst_sbc_get_mode_string(int joint)
 {
 	switch (joint) {
-	case CFG_MODE_MONO:
+	case BT_A2DP_CHANNEL_MODE_MONO:
 		return "mono";
-	case CFG_MODE_DUAL_CHANNEL:
+	case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
 		return "dual";
-	case CFG_MODE_STEREO:
+	case BT_A2DP_CHANNEL_MODE_STEREO:
 		return "stereo";
-	case CFG_MODE_JOINT_STEREO:
+	case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
 		return "joint";
-	case CFG_MODE_AUTO:
+	case BT_A2DP_CHANNEL_MODE_AUTO:
 		return NULL; /* TODO what should be selected here? */
 	default:
 		return NULL;
@@ -145,37 +145,172 @@ const gchar *gst_sbc_get_mode_string(int joint)
 const gchar *gst_sbc_get_allocation_string(int alloc)
 {
 	switch (alloc) {
-	case CFG_ALLOCATION_LOUDNESS:
+	case BT_A2DP_ALLOCATION_LOUDNESS:
 		return "loudness";
-	case CFG_ALLOCATION_SNR:
+	case BT_A2DP_ALLOCATION_SNR:
 		return "snr";
-	case CFG_ALLOCATION_AUTO:
+	case BT_A2DP_ALLOCATION_AUTO:
 		return "loudness"; /* TODO what should be selected here? */
 	default:
 		return NULL;
 	}
 }
 
-GstCaps* gst_sbc_caps_from_sbc(struct ipc_data_cfg *cfg,
-		struct ipc_codec_sbc *sbc, gint channels)
+GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels)
 {
 	GstCaps *caps;
 	const gchar *mode_str;
 	const gchar *allocation_str;
 
-	mode_str = gst_sbc_get_mode_string(cfg->mode);
-	allocation_str = gst_sbc_get_allocation_string(sbc->allocation);
+	mode_str = gst_sbc_get_mode_string(sbc->channel_mode);
+	allocation_str = gst_sbc_get_allocation_string(sbc->allocation_method);
 
 	caps = gst_caps_new_simple("audio/x-sbc",
-				"rate", G_TYPE_INT, cfg->rate,
+				"rate", G_TYPE_INT, sbc->frequency,
 				"channels", G_TYPE_INT, channels,
 				"mode", G_TYPE_STRING, mode_str,
 				"subbands", G_TYPE_INT, sbc->subbands,
-				"blocks", G_TYPE_INT, sbc->blocks,
+				"blocks", G_TYPE_INT, sbc->block_length,
 				"allocation", G_TYPE_STRING, allocation_str,
-				"bitpool", G_TYPE_INT, sbc->bitpool,
+				"bitpool", G_TYPE_INT, sbc->max_bitpool,
 				NULL);
 
 	return caps;
 }
 
+/*
+ * Given a GstCaps, this will return a fixed GstCaps on sucessfull conversion.
+ * If an error occurs, it will return NULL and error_message will contain the
+ * error message.
+ *
+ * error_message must be passed NULL, if an error occurs, the caller has the
+ * ownership of the error_message, it must be freed after use.
+ */
+GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message)
+{
+	GstCaps *result;
+	GstStructure *structure;
+	const GValue *value;
+	gboolean error = FALSE;
+	gint temp, rate, channels, blocks, subbands, bitpool;
+	const gchar* allocation = NULL;
+	const gchar* mode = NULL;
+
+	g_assert(*error_message == NULL);
+
+	structure = gst_caps_get_structure(caps, 0);
+
+	if (!gst_structure_has_field(structure, "rate")) {
+		error = TRUE;
+		*error_message = g_strdup("no rate");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "rate");
+		if (GST_VALUE_HOLDS_LIST(value)) {
+			temp = gst_sbc_select_rate_from_list(value);
+		} else {
+			temp = g_value_get_int(value);
+		}
+		rate = temp;
+	}
+
+	if (!gst_structure_has_field(structure, "channels")) {
+		error = TRUE;
+		*error_message = g_strdup("no channels");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "channels");
+		if (GST_VALUE_HOLDS_INT_RANGE(value)) {
+			temp = gst_sbc_select_channels_from_range(value);
+		} else {
+			temp = g_value_get_int(value);
+		}
+		channels = temp;
+	}
+
+	if (!gst_structure_has_field(structure, "blocks")) {
+		error = TRUE;
+		*error_message = g_strdup("no blocks.");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "blocks");
+		if (GST_VALUE_HOLDS_LIST(value)) {
+			temp = gst_sbc_select_blocks_from_list(value);
+		} else {
+			temp = g_value_get_int(value);
+		}
+		blocks = temp;
+	}
+
+	if (!gst_structure_has_field(structure, "subbands")) {
+		error = TRUE;
+		*error_message = g_strdup("no subbands");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "subbands");
+		if (GST_VALUE_HOLDS_LIST(value)) {
+			temp = gst_sbc_select_subbands_from_list(value);
+		} else {
+			temp = g_value_get_int(value);
+		}
+		subbands = temp;
+	}
+
+	if (!gst_structure_has_field(structure, "bitpool")) {
+		error = TRUE;
+		*error_message = g_strdup("no bitpool");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "bitpool");
+		if (GST_VALUE_HOLDS_INT_RANGE(value)) {
+			temp = gst_sbc_select_bitpool_from_range(value);
+		} else {
+			temp = g_value_get_int(value);
+		}
+		bitpool = temp;
+	}
+
+	if (!gst_structure_has_field(structure, "allocation")) {
+		error = TRUE;
+		*error_message = g_strdup("no allocation");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "allocation");
+		if (GST_VALUE_HOLDS_LIST(value)) {
+			allocation = gst_sbc_get_allocation_from_list(value);
+		} else {
+			allocation = g_value_get_string(value);
+		}
+	}
+
+	if (!gst_structure_has_field(structure, "mode")) {
+		error = TRUE;
+		*error_message = g_strdup("no mode");
+		goto error;
+	} else {
+		value = gst_structure_get_value(structure, "mode");
+		if (GST_VALUE_HOLDS_LIST(value)) {
+			mode = gst_sbc_get_mode_from_list(value);
+		} else {
+			mode = g_value_get_string(value);
+		}
+	}
+
+error:
+	if (error)
+		return NULL;
+
+	result = gst_caps_new_simple("audio/x-sbc",
+					"rate", G_TYPE_INT, rate,
+					"channels", G_TYPE_INT, channels,
+					"mode", G_TYPE_STRING, mode,
+					"blocks", G_TYPE_INT, blocks,
+					"subbands", G_TYPE_INT, subbands,
+					"allocation", G_TYPE_STRING, allocation,
+					"bitpool", G_TYPE_INT, bitpool,
+					NULL);
+
+	return result;
+}
+
+
diff --git a/audio/gstsbcutil.h b/audio/gstsbcutil.h
index 0c91fe8..4581abf 100644
--- a/audio/gstsbcutil.h
+++ b/audio/gstsbcutil.h
@@ -22,10 +22,9 @@
  */
 
 #include <gst/gst.h>
-#include "sbc.h"
 
-struct ipc_data_cfg; /* FIXME can't include ipc.h */
-struct ipc_codec_sbc;
+#include "sbc.h"
+#include "ipc.h"
 
 gint gst_sbc_select_rate_from_list(const GValue *value);
 
@@ -47,6 +46,6 @@ const gchar *gst_sbc_get_mode_from_list(const GValue *value);
 gint gst_sbc_get_mode_int(const gchar *mode);
 const gchar *gst_sbc_get_mode_string(int joint);
 
-GstCaps* gst_sbc_caps_from_sbc(struct ipc_data_cfg *cfg, struct ipc_codec_sbc *sbc,
-		gint channels);
+GstCaps* gst_sbc_caps_from_sbc(sbc_capabilities_t *sbc, gint channels);
 
+GstCaps* gst_sbc_util_caps_fixate(GstCaps *caps, gchar** error_message);
diff --git a/audio/ipc.c b/audio/ipc.c
new file mode 100644
index 0000000..5d6cb62
--- /dev/null
+++ b/audio/ipc.c
@@ -0,0 +1,94 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "ipc.h"
+
+int bt_audio_service_open()
+{
+	int sk;
+	int err;
+	struct sockaddr_un addr = {
+		AF_UNIX, BT_IPC_SOCKET_NAME
+	};
+
+	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (sk < 0) {
+		err = errno;
+		fprintf(stderr, "%s: Cannot open socket: %s (%d)\n",
+			__FUNCTION__, strerror(err), err);
+		errno = err;
+		return -1;
+	}
+
+	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		err = errno;
+		fprintf(stderr, "%s: connect() failed: %s (%d)\n", 
+			__FUNCTION__, strerror(err), err);
+		close(sk);
+		errno = err;
+		return -1;
+	}
+
+	return sk;
+}
+
+int bt_audio_service_close(int sk)
+{
+	return close(sk);
+}
+
+int bt_audio_service_get_data_fd(int sk)
+{
+	char cmsg_b[CMSG_SPACE(sizeof(int))], m;
+	int err, ret;
+	struct iovec iov = { &m, sizeof(m) };
+	struct msghdr msgh;
+	struct cmsghdr *cmsg;
+
+	memset(&msgh, 0, sizeof(msgh));
+	msgh.msg_iov = &iov;
+	msgh.msg_iovlen = 1;
+	msgh.msg_control = &cmsg_b;
+	msgh.msg_controllen = CMSG_LEN(sizeof(int));
+
+	ret = recvmsg(sk, &msgh, 0);
+	if (ret < 0) {
+		err = errno;
+		fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n",
+			__FUNCTION__, strerror(err), err);
+		errno = err;
+		return -1;
+	}
+
+	/* Receive auxiliary data in msgh */
+	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+			cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+		if (cmsg->cmsg_level == SOL_SOCKET
+				&& cmsg->cmsg_type == SCM_RIGHTS) {
+			return (*(int *) CMSG_DATA(cmsg));
+		}
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
diff --git a/audio/ipc.h b/audio/ipc.h
index 1c26e30..550448b 100644
--- a/audio/ipc.h
+++ b/audio/ipc.h
@@ -4,132 +4,302 @@
  *
  *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
  *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
+ *  This library is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
 
-#include <stdint.h>
+/*
+  Message sequence chart of streaming sequence for A2DP transport
+
+  Audio daemon                       User
+                             on snd_pcm_open
+                 <--BT_GETCAPABILITIES_REQ
+
+  BT_GETCAPABILITIES_RSP-->
+
+                        on snd_pcm_hw_params
+                <--BT_SETCONFIGURATION_REQ
+
+  BT_SETCONFIGURATION_RSP-->
+
+			on snd_pcm_prepare
+                <--BT_STREAMSTART_REQ
+
+  <Moves to streaming state>
+  BT_STREAMSTART_RSP-->
 
-#define IPC_TYPE_CONNECT  0x0001
+  BT_STREAMFD_IND -->
 
-#define IPC_MTU 128
+                          <  streams data >
+                             ..........
 
-#define IPC_SOCKET_NAME "\0/org/bluez/audio"
+               on snd_pcm_drop/snd_pcm_drain
 
-#ifndef UNIX_PATH_MAX
-#define UNIX_PATH_MAX 108
+                <--BT_STREAMSTOP_REQ
+
+  <Moves to open state>
+  BT_STREAMSTOP_RSP-->
+
+			on IPC close or appl crash
+  <Moves to idle>
+
+ */
+
+#ifndef BT_AUDIOCLIENT_H
+#define BT_AUDIOCLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-/* Supported roles */
-#define PKT_ROLE_AUTO			0
-#define PKT_ROLE_VOICE			1
-#define PKT_ROLE_HIFI			2
-
-/* Packet types */
-#define PKT_TYPE_CFG_REQ		0
-#define PKT_TYPE_CFG_RSP		1
-#define PKT_TYPE_STATE_REQ		2
-#define PKT_TYPE_STATE_RSP		3
-#define PKT_TYPE_CTL_REQ		4
-#define PKT_TYPE_CTL_RSP		5
-#define PKT_TYPE_CTL_NTFY		6
-
-/* Errors codes */
-#define PKT_ERROR_NONE			0
-
-struct ipc_packet {
-	char device[18];	/* Address of the remote Device */
-	uint8_t role;		/* Audio role eg: voice, wifi, auto... */
-	uint8_t type;		/* Packet type */
-	uint8_t error;		/* Packet error code */
-	uint8_t length;		/* Payload length in bytes */
-	uint8_t data[0];	/* Packet payload */
-} __attribute__ ((packed));
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#define BT_AUDIO_IPC_PACKET_SIZE   128
+#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
 
-/* File descriptor options */
-#define CFG_FD_OPT_READ		0
-#define CFG_FD_OPT_WRITE	1
-#define CFG_FD_OPT_READWRITE	2
-
-/* Audio channel mode */
-#define CFG_MODE_AUTO		0
-#define CFG_MODE_MONO		1
-#define CFG_MODE_DUAL_CHANNEL	2
-#define CFG_MODE_STEREO		3
-#define CFG_MODE_JOINT_STEREO	4
-
-/* Allocation method */
-#define CFG_ALLOCATION_AUTO	0
-#define CFG_ALLOCATION_LOUDNESS	1
-#define CFG_ALLOCATION_SNR	2
-
-/* Codec options */
-#define CFG_CODEC_NONE		0
-#define CFG_CODEC_SCO		1
-#define CFG_CODEC_SBC		2
-
-struct ipc_data_cfg {
-	uint8_t  fd_opt;	/* Stream file descriptor options: read,
-				   write or readwrite */
-	uint16_t pkt_len;	/* Stream packet length */
-	uint8_t  sample_size;	/* Sample size in bytes */
-	uint8_t  mode;		/* Audio channel mode */
-	uint16_t rate;		/* Stream sample rate */
-	uint8_t  codec;		/* Stream codec */
-	uint8_t  data[0];	/* Codec payload */
+/* Generic message header definition */
+typedef struct {
+	uint8_t msg_type;
+} __attribute__ ((packed)) bt_audio_msg_header_t;
+
+/* Messages list */
+#define BT_GETCAPABILITIES_REQ		0
+#define BT_GETCAPABILITIES_RSP		1
+
+#define BT_SETCONFIGURATION_REQ		2
+#define BT_SETCONFIGURATION_RSP		3
+
+#define BT_STREAMSTART_REQ		4
+#define BT_STREAMSTART_RSP		5
+
+#define BT_STREAMSTOP_REQ		6
+#define BT_STREAMSTOP_RSP		7
+
+#define BT_STREAMSUSPEND_IND		8
+#define BT_STREAMRESUME_IND		9
+
+#define BT_CONTROL_REQ		       10
+#define BT_CONTROL_RSP		       11
+#define BT_CONTROL_IND		       12
+
+#define BT_STREAMFD_IND		       13
+
+/* This table contains the string representation for messages above */
+static const char *bt_audio_strmsg[] = {
+	"BT_GETCAPABILITIES_REQ",
+	"BT_GETCAPABILITIES_RSP",
+	"BT_SETCONFIGURATION_REQ",
+	"BT_SETCONFIGURATION_RSP",
+	"BT_STREAMSTART_REQ",
+	"BT_STREAMSTART_RSP",
+	"BT_STREAMSTOP_REQ",
+	"BT_STREAMSTOP_RSP",
+	"BT_STREAMSUSPEND_IND",
+	"BT_STREAMRESUME_IND",
+	"BT_CONTROL_REQ",
+	"BT_CONTROL_RSP",
+	"BT_CONTROL_IND",
+	"BT_STREAMFD_IND",
+};
+
+#define BT_MSG_MAX ((sizeof(bt_audio_strmsg) / sizeof(char*)) -1)
+
+/* BT_GETCAPABILITIES_REQ */
+
+#define BT_CAPABILITIES_TRANSPORT_A2DP	0
+#define BT_CAPABILITIES_TRANSPORT_SCO	1
+#define BT_CAPABILITIES_TRANSPORT_ANY	2
+
+#define BT_CAPABILITIES_ACCESS_MODE_READ	1
+#define BT_CAPABILITIES_ACCESS_MODE_WRITE	2
+#define BT_CAPABILITIES_ACCESS_MODE_READWRITE	3
+
+struct bt_getcapabilities_req {
+	bt_audio_msg_header_t	h;
+	char			device[18];	/* Address of the remote Device */
+	uint8_t			transport;	/* Requested transport */
+	uint8_t			access_mode;	/* Requested access mode */
 } __attribute__ ((packed));
 
-struct ipc_codec_sbc {
-	uint8_t allocation;
+/* BT_GETCAPABILITIES_RSP */
+
+/**
+ * SBC Codec parameters as per A2DP profile 1.0 § 4.3
+ */
+
+#define BT_A2DP_SAMPLING_FREQ_16000		(1 << 3)
+#define BT_A2DP_SAMPLING_FREQ_32000		(1 << 2)
+#define BT_A2DP_SAMPLING_FREQ_44100		(1 << 1)
+#define BT_A2DP_SAMPLING_FREQ_48000		1
+
+#define BT_A2DP_CHANNEL_MODE_MONO		(1 << 3)
+#define BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2)
+#define BT_A2DP_CHANNEL_MODE_STEREO		(1 << 1)
+#define BT_A2DP_CHANNEL_MODE_JOINT_STEREO	1
+#define BT_A2DP_CHANNEL_MODE_AUTO		0
+
+#define BT_A2DP_BLOCK_LENGTH_4			(1 << 3)
+#define BT_A2DP_BLOCK_LENGTH_8			(1 << 2)
+#define BT_A2DP_BLOCK_LENGTH_12			(1 << 1)
+#define BT_A2DP_BLOCK_LENGTH_16			1
+
+#define BT_A2DP_SUBBANDS_4			(1 << 1)
+#define BT_A2DP_SUBBANDS_8			1
+
+#define BT_A2DP_ALLOCATION_SNR			(1 << 1)
+#define BT_A2DP_ALLOCATION_LOUDNESS		1
+#define BT_A2DP_ALLOCATION_AUTO			0
+
+typedef struct {
+	uint8_t channel_mode;
+	uint8_t frequency;
+	uint8_t allocation_method;
 	uint8_t subbands;
-	uint8_t blocks;
-	uint8_t bitpool;
+	uint8_t block_length;
+	uint8_t min_bitpool;
+	uint8_t max_bitpool;
+} __attribute__ ((packed)) sbc_capabilities_t;
+
+/* To be defined */
+typedef struct {
+} __attribute__ ((packed)) mpeg_capabilities_t;
+
+struct bt_getcapabilities_rsp {
+	bt_audio_msg_header_t	h;
+	uint8_t			posix_errno;
+	uint8_t			transport;		/* Granted transport */
+	uint8_t			access_mode;		/* Granted access mode */
+	uint16_t		link_mtu;		/* Max length that transport supports */
+	sbc_capabilities_t	sbc_capabilities;	/* A2DP only */
+	mpeg_capabilities_t	mpeg_capabilities;	/* A2DP only */
+	uint16_t		sampling_rate;		/* SCO only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_REQ */
+struct bt_setconfiguration_req {
+	bt_audio_msg_header_t	h;
+	char			device[18];		/* Address of the remote Device */
+	sbc_capabilities_t	sbc_capabilities;	/* A2DP only - only one of this field
+							and next one must be filled */
+	mpeg_capabilities_t	mpeg_capabilities;	/* A2DP only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_RSP */
+struct bt_setconfiguration_rsp {
+	bt_audio_msg_header_t	h;
+	uint8_t			posix_errno;
 } __attribute__ ((packed));
 
-/* Device status */
-#define STATE_DISCONNECTED		0
-#define STATE_CONNECTING		1
-#define STATE_CONNECTED			2
-#define STATE_STREAM_STARTING		3
-#define STATE_STREAMING			4
+/* BT_STREAMSTART_REQ */
+#define BT_STREAM_ACCESS_READ		0
+#define BT_STREAM_ACCESS_WRITE		1
+#define BT_STREAM_ACCESS_READWRITE	2
+struct bt_streamstart_req {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
 
-struct ipc_data_state {
-	uint8_t state;		/* Stream state */
+/* BT_STREAMSTART_RSP */
+struct bt_streamstart_rsp {
+	bt_audio_msg_header_t	h;
+	uint8_t			posix_errno;
 } __attribute__ ((packed));
 
-#define CTL_MODE_PLAYBACK		0
-#define CTL_MODE_CAPTURE		1
-#define CTL_MODE_GENERAL		2
-
-/* Supported control operations */
-#define CTL_KEY_POWER			0x40
-#define CTL_KEY_VOL_UP			0x41
-#define CTL_KEY_VOL_DOWN		0x42
-#define CTL_KEY_MUTE			0x43
-#define CTL_KEY_PLAY			0x44
-#define CTL_KEY_STOP			0x45
-#define CTL_KEY_PAUSE			0x46
-#define CTL_KEY_RECORD			0x47
-#define CTL_KEY_REWIND			0x48
-#define CTL_KEY_FAST_FORWARD		0x49
-#define CTL_KEY_EJECT			0x4A
-#define CTL_KEY_FORWARD			0x4B
-#define CTL_KEY_BACKWARD		0x4C
-
-struct ipc_data_ctl {
-	uint8_t mode;		/* Control Mode */
-	uint8_t key;		/* Control Key */
-}  __attribute__ ((packed));
+/* BT_STREAMFD_IND */
+/* This message is followed by one byte of data containing the stream data fd
+   as ancilliary data */
+struct bt_datafd_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_REQ */
+struct bt_streamstop_req {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_RSP */
+struct bt_streamstop_rsp {
+	bt_audio_msg_header_t	h;
+	uint8_t			posix_errno;
+} __attribute__ ((packed));
+
+/* BT_STREAMSUSPEND_IND */
+struct bt_streamsuspend_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMRESUME_IND */
+struct bt_streamresume_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_CONTROL_REQ */
+
+#define BT_CONTROL_KEY_POWER			0x40
+#define BT_CONTROL_KEY_VOL_UP			0x41
+#define BT_CONTROL_KEY_VOL_DOWN			0x42
+#define BT_CONTROL_KEY_MUTE			0x43
+#define BT_CONTROL_KEY_PLAY			0x44
+#define BT_CONTROL_KEY_STOP			0x45
+#define BT_CONTROL_KEY_PAUSE			0x46
+#define BT_CONTROL_KEY_RECORD			0x47
+#define BT_CONTROL_KEY_REWIND			0x48
+#define BT_CONTROL_KEY_FAST_FORWARD		0x49
+#define BT_CONTROL_KEY_EJECT			0x4A
+#define BT_CONTROL_KEY_FORWARD			0x4B
+#define BT_CONTROL_KEY_BACKWARD			0x4C
+
+struct bt_control_req {
+	bt_audio_msg_header_t	h;
+	uint8_t			mode;		/* Control Mode */
+	uint8_t			key;		/* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_RSP */
+struct bt_control_rsp {
+	bt_audio_msg_header_t	h;
+	uint8_t			posix_errno;
+	uint8_t			mode;		/* Control Mode */
+	uint8_t			key;		/* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_IND */
+struct bt_control_ind {
+	bt_audio_msg_header_t	h;
+	uint8_t			mode;		/* Control Mode */
+	uint8_t			key;		/* Control Key */
+} __attribute__ ((packed));
+
+/* Function declaration */
+
+/* Opens a connection to the audio service: return a socket descriptor */
+int bt_audio_service_open();
+
+/* Closes a connection to the audio service */
+int bt_audio_service_close(int sk);
+
+/* Receives stream data file descriptor : must be called after a
+BT_STREAMFD_IND message is returned */
+int bt_audio_service_get_data_fd(int sk);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_AUDIOCLIENT_H */
diff --git a/audio/manager.c b/audio/manager.c
index b0cc334..d80fb96 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -1052,7 +1052,7 @@ static void parse_stored_devices(char *key, char *value, void *data)
 		return;
 
 	str2ba(key, &dst);
-	device = manager_find_device(&dst, PKT_ROLE_AUTO, FALSE);
+	device = manager_find_device(&dst, NULL, FALSE);
 
 	if (device)
 		return;
@@ -1111,7 +1111,7 @@ static void register_devices_stored(const char *adapter)
 		return;
 
 	str2ba(addr, &dst);
-	device = manager_find_device(&dst, PKT_ROLE_AUTO, FALSE);
+	device = manager_find_device(&dst, NULL, FALSE);
 
 	if (device) {
 		info("Setting %s as default device", addr);
diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c
index efe1d2a..9e04023 100644
--- a/audio/pcm_bluetooth.c
+++ b/audio/pcm_bluetooth.c
@@ -76,33 +76,60 @@
 #endif
 
 struct bluetooth_a2dp {
-	sbc_t sbc;			/* Codec data */
-	int codesize;			/* SBC codesize */
-	int samples;			/* Number of encoded samples */
-	uint8_t buffer[BUFFER_SIZE];	/* Codec transfer buffer */
-	int count;			/* Codec transfer buffer counter */
-
-	int nsamples;			/* Cumulative number of codec samples */
-	uint16_t seq_num;		/* Cumulative packet sequence */
-	int frame_count;		/* Current frames in buffer*/
+	sbc_capabilities_t sbc_capabilities;
+	sbc_t sbc;				/* Codec data */
+	int sbc_initialized;			/* Keep track if the encoder is initialized */
+	int codesize;				/* SBC codesize */
+	int samples;				/* Number of encoded samples */
+	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
+	int count;				/* Codec transfer buffer counter */
+
+	int nsamples;				/* Cumulative number of codec samples */
+	uint16_t seq_num;			/* Cumulative packet sequence */
+	int frame_count;			/* Current frames in buffer*/
+};
+
+struct bluetooth_alsa_config {
+	char device[18];		/* Address of the remote Device */
+	int has_device;
+	uint8_t transport;		/* Requested transport */
+	int has_transport;
+	uint16_t rate;
+	int has_rate;
+	uint8_t channel_mode;		/* A2DP only */
+	int has_channel_mode;
+	uint8_t allocation_method;	/* A2DP only */
+	int has_allocation_method;
+	uint8_t subbands;		/* A2DP only */
+	int has_subbands;
+	uint8_t block_length;		/* A2DP only */
+	int has_block_length;
+	uint8_t bitpool;		/* A2DP only */
+	int has_bitpool;
 };
 
 struct bluetooth_data {
 	snd_pcm_ioplug_t io;
+	struct bluetooth_alsa_config alsa_config;	/* ALSA resource file parameters */
 	volatile snd_pcm_sframes_t hw_ptr;
-	struct ipc_data_cfg cfg;	/* Bluetooth device config */
-	struct pollfd stream;		/* Audio stream filedescriptor */
-	struct pollfd server;		/* Audio daemon filedescriptor */
-	uint8_t buffer[BUFFER_SIZE];	/* Encoded transfer buffer */
-	int count;			/* Transfer buffer counter */
-	struct bluetooth_a2dp a2dp;	/* A2DP data */
-
-	pthread_t hw_thread;		/* Makes virtual hw pointer move */
-	int pipefd[2];			/* Inter thread communication */
+	int transport;					/* chosen transport SCO or AD2P */
+	int link_mtu;					/* MTU for selected transport channel */
+	volatile struct pollfd stream;			/* Audio stream filedescriptor */
+	struct pollfd server;				/* Audio daemon filedescriptor */
+	uint8_t buffer[BUFFER_SIZE];		/* Encoded transfer buffer */
+	int count;					/* Transfer buffer counter */
+	struct bluetooth_a2dp a2dp;			/* A2DP data */
+
+	pthread_t hw_thread;				/* Makes virtual hw pointer move */
+	int pipefd[2];					/* Inter thread communication */
 	int stopped;
 	sig_atomic_t reset;             /* Request XRUN handling */
 };
 
+static int audioservice_send(int sk, const bt_audio_msg_header_t *msg);
+static int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg,
+				int expected_type);
+
 static int bluetooth_start(snd_pcm_ioplug_t *io)
 {
 	DBG("bluetooth_start %p", io);
@@ -215,62 +242,6 @@ iter_sleep:
 	pthread_exit(NULL);
 }
 
-#if 0
-static int bluetooth_state_init(struct ipc_packet *pkt, int newstate)
-{
-	struct ipc_data_state *state = (void *) pkt->data;
-
-	pkt->length = sizeof(*state);
-	pkt->type = PKT_TYPE_STATE_REQ;
-	pkt->error = PKT_ERROR_NONE;
-	state->state = newstate;
-
-	return 0;
-}
-
-static int bluetooth_state(struct bluetooth_data *data, int newstate)
-{
-	char buf[IPC_MTU];
-	struct ipc_packet *pkt = (void *) buf;
-	struct ipc_data_state *state = (void *) pkt->data;
-	int ret;
-
-	memset(buf, 0, sizeof(buf));
-
-	ret = bluetooth_state_init(pkt, newstate);
-	if (ret < 0)
-		return -ret;
-
-	ret = send(data->server.fd, pkt, sizeof(*pkt) + pkt->length, 0);
-	if (ret < 0)
-		return -errno;
-	else if (ret == 0)
-		return -EIO;
-
-	DBG("OK - %d bytes sent. Waiting for response...", ret);
-
-	memset(buf, 0, sizeof(buf));
-
-	ret = recv(data->server.fd, buf, sizeof(*pkt) + sizeof(*state), 0);
-	if (ret < 0)
-		return -errno;
-	else if (ret == 0)
-		return -EIO;
-
-	if (pkt->type != PKT_TYPE_STATE_RSP) {
-		SNDERR("Unexpected packet type %d received", pkt->type);
-		return -EINVAL;
-	}
-
-	if (pkt->error != PKT_ERROR_NONE) {
-		SNDERR("Error %d while configuring device", pkt->error);
-		return -pkt->error;
-	}
-
-	return 0;
-}
-#endif
-
 static int bluetooth_playback_start(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
@@ -278,9 +249,6 @@ static int bluetooth_playback_start(snd_pcm_ioplug_t *io)
 
 	DBG("%p", io);
 
-#if 0
-	bluetooth_state(data, STATE_STREAMING);
-#endif
 	data->stopped = 0;
 
 	if (data->hw_thread)
@@ -297,9 +265,6 @@ static int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
 
 	DBG("%p", io);
 
-#if 0
-	bluetooth_state(data, STATE_CONNECTED);
-#endif
 	data->stopped = 1;
 
 	return 0;
@@ -317,7 +282,7 @@ static void bluetooth_exit(struct bluetooth_data *data)
 	struct bluetooth_a2dp *a2dp = &data->a2dp;
 
 	if (data->server.fd >= 0)
-		close(data->server.fd);
+		bt_audio_service_close(data->server.fd);
 
 	if (data->stream.fd >= 0)
 		close(data->stream.fd);
@@ -327,7 +292,7 @@ static void bluetooth_exit(struct bluetooth_data *data)
 		pthread_join(data->hw_thread, 0);
 	}
 
-	if (data->cfg.codec == CFG_CODEC_SBC)
+	if (a2dp->sbc_initialized)
 		sbc_finish(&a2dp->sbc);
 
 	if (data->pipefd[0] > 0)
@@ -354,12 +319,27 @@ static int bluetooth_prepare(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
 	char c = 'w';
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_streamstart_req *start_req = (void*) buf;
+	struct bt_streamstart_rsp *start_rsp = (void*) buf;
+	struct bt_datafd_ind *datafd_ind = (void*) buf;
+	uint32_t period_count = io->buffer_size / io->period_size;
+	int opt_name, err;
+	struct timeval t = { 0, period_count };
 
 	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
 					io->period_size, io->buffer_size);
 
 	data->reset = 0;
 
+	/* As we're gonna receive messages on the server socket, we have to stop the
+	   hw thread that is polling on it, if any */
+	if (data->hw_thread) {
+		pthread_cancel(data->hw_thread);
+		pthread_join(data->hw_thread, 0);
+		data->hw_thread = 0;
+	}
+
 	if (io->stream == SND_PCM_STREAM_PLAYBACK)
 		/* If not null for playback, xmms doesn't display time
 		 * correctly */
@@ -369,63 +349,172 @@ static int bluetooth_prepare(snd_pcm_ioplug_t *io)
 		 * If it is, capture won't start */
 		data->hw_ptr = io->period_size;
 
-	/* wake up any client polling at us */
-	return write(data->pipefd[1], &c, 1);
-}
+	/* send start */
+	memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+	start_req->h.msg_type = BT_STREAMSTART_REQ;
 
-static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
-					snd_pcm_hw_params_t *params)
-{
-	struct bluetooth_data *data = io->private_data;
-	uint32_t period_count = io->buffer_size / io->period_size;
-	int opt_name, err;
+	err = audioservice_send(data->server.fd, &start_req->h);
+	if (err < 0)
+		return err;
+
+	err = audioservice_expect(data->server.fd, &start_rsp->h, BT_STREAMSTART_RSP);
+	if (err < 0)
+		return err;
+
+	if (start_rsp->posix_errno != 0) {
+		SNDERR("BT_START failed : %s(%d)",
+					strerror(start_rsp->posix_errno),
+					start_rsp->posix_errno);
+		return -start_rsp->posix_errno;
+	}
+
+	err = audioservice_expect(data->server.fd, &datafd_ind->h, BT_STREAMFD_IND);
+	if (err < 0)
+		return err;
+
+	if (data->stream.fd >= 0)
+		close(data->stream.fd);
 
-	DBG("fd=%d period_count=%d", data->stream.fd, period_count);
+	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
+	if (data->stream.fd < 0) {
+		return -errno;
+	}
+
+	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
+						SO_SNDTIMEO : SO_RCVTIMEO;
 
-	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
+		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
+							sizeof(t)) < 0) {
+			return -errno;
+		}
+	} else {
+		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
 						SCO_TXBUFS : SCO_RXBUFS;
 
-	if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
+		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
 						sizeof(period_count)) == 0)
-		return 0;
+			return 0;
 
-	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
+		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
 						SO_SNDBUF : SO_RCVBUF;
 
-	if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
+		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
 						sizeof(period_count)) == 0)
-		return 0;
-
-	err = errno;
+			return 0;
 
-	SNDERR("%s (%d)", strerror(err), err);
+		/* FIXME : handle error codes */
+	}
 
-	/* FIXME: We should not ignores errors in the future. */
-	return 0;
+	/* wake up any client polling at us */
+	return write(data->pipefd[1], &c, 1);
 }
 
 static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
 					snd_pcm_hw_params_t *params)
 {
 	struct bluetooth_data *data = io->private_data;
-	uint32_t period_count = io->buffer_size / io->period_size;
-	int opt_name, err;
-	struct timeval t = { 0, period_count };
+	struct bluetooth_a2dp *a2dp = &data->a2dp;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_setconfiguration_req *setconf_req = (void*) buf;
+	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
+	int err;
+	sbc_capabilities_t active_capabilities;
 
-	DBG("fd=%d period_count=%d", data->stream.fd, period_count);
+	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
+					io->period_size, io->buffer_size);
 
-	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
-						SO_SNDTIMEO : SO_RCVTIMEO;
+	/* FIXME: this needs to be really implemented (take into account
+	real asoundrc settings + ALSA hw settings ) once server side sends us
+	more than one possible configuration */
+	active_capabilities = a2dp->sbc_capabilities;
 
-	if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
-							sizeof(t)) == 0)
-		return 0;
+	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
+	setconf_req->sbc_capabilities = active_capabilities;
 
-	err = errno;
+	err = audioservice_send(data->server.fd, &setconf_req->h);
+	if (err < 0)
+		return err;
 
-	SNDERR("%s (%d)", strerror(err), err);
+	err = audioservice_expect(data->server.fd, &setconf_rsp->h, BT_SETCONFIGURATION_RSP);
+	if (err < 0)
+		return err;
 
-	return -err;
+	if (setconf_rsp->posix_errno != 0) {
+		SNDERR("BT_SETCONFIGURATION failed : %s(%d)",
+					strerror(setconf_rsp->posix_errno),
+					setconf_rsp->posix_errno);
+		return -setconf_rsp->posix_errno;
+	}
+
+	/* Setup SBC encoder now we agree on parameters */
+	if (a2dp->sbc_initialized)
+		sbc_finish(&a2dp->sbc);
+
+	/* FIXME: init using flags? */
+	sbc_init(&a2dp->sbc, 0);
+	a2dp->sbc_initialized = 1;
+	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000)
+		a2dp->sbc.rate = 16000;
+
+	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000)
+		a2dp->sbc.rate = 32000;
+
+	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100)
+		a2dp->sbc.rate = 44100;
+
+	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000)
+		a2dp->sbc.rate = 48000;
+
+	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+		a2dp->sbc.channels = 1;
+	else
+		a2dp->sbc.channels = 2;
+
+	if (active_capabilities.channel_mode &
+			(BT_A2DP_CHANNEL_MODE_MONO || BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
+		a2dp->sbc.joint = 1;
+	else
+		a2dp->sbc.joint = 0;
+
+	a2dp->sbc.allocation = active_capabilities.allocation_method
+					== BT_A2DP_ALLOCATION_SNR ? 0x01 : 0x00;
+
+	switch (active_capabilities.subbands) {
+	case BT_A2DP_SUBBANDS_4:
+		a2dp->sbc.subbands = 4;
+		break;
+	case BT_A2DP_SUBBANDS_8:
+		a2dp->sbc.subbands = 8;
+		break;
+	}
+
+	switch (active_capabilities.block_length) {
+	case BT_A2DP_BLOCK_LENGTH_4:
+		a2dp->sbc.blocks = 4;
+		break;
+	case BT_A2DP_BLOCK_LENGTH_8:
+		a2dp->sbc.blocks = 8;
+		break;
+	case BT_A2DP_BLOCK_LENGTH_12:
+		a2dp->sbc.blocks = 12;
+		break;
+	case BT_A2DP_BLOCK_LENGTH_16:
+		a2dp->sbc.blocks = 16;
+		break;
+	}
+
+	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
+	a2dp->codesize = a2dp->sbc.subbands * a2dp->sbc.blocks *
+						a2dp->sbc.channels * 2;
+	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+
+	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
+		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
+		a2dp->sbc.bitpool);
+
+	return 0;
 }
 
 static int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
@@ -504,7 +593,6 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
 				snd_pcm_uframes_t size)
 {
 	struct bluetooth_data *data = io->private_data;
-	struct ipc_data_cfg cfg = data->cfg;
 	snd_pcm_uframes_t frames_to_write, ret;
 	unsigned char *buff;
 	int nrecv, frame_size = 0;
@@ -517,7 +605,7 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
 
 	frame_size = areas->step / 8;
 
-	nrecv = recv(data->stream.fd, data->buffer, cfg.pkt_len,
+	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
 			MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0));
 
 	if (nrecv < 0) {
@@ -525,28 +613,28 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
 		goto done;
 	}
 
-	if (nrecv != cfg.pkt_len) {
+	if (nrecv != data->link_mtu) {
 		ret = -EIO;
 		SNDERR(strerror(-ret));
 		goto done;
 	}
 
 	/* Increment hardware transmition pointer */
-	data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) %
+	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
 								io->buffer_size;
 
 proceed:
 	buff = (unsigned char *) areas->addr +
 			(areas->first + areas->step * offset) / 8;
 
-	if ((data->count + size * frame_size) <= cfg.pkt_len)
+	if ((data->count + size * frame_size) <= data->link_mtu)
 		frames_to_write = size;
 	else
-		frames_to_write = (cfg.pkt_len - data->count) / frame_size;
+		frames_to_write = (data->link_mtu - data->count) / frame_size;
 
 	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
 	data->count += (frame_size * frames_to_write);
-	data->count %= cfg.pkt_len;
+	data->count %= data->link_mtu;
 
 	/* Return written frames count */
 	ret = frames_to_write;
@@ -562,7 +650,6 @@ static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
 				snd_pcm_uframes_t size)
 {
 	struct bluetooth_data *data = io->private_data;
-	struct ipc_data_cfg cfg = data->cfg;
 	snd_pcm_sframes_t ret = 0;
 	snd_pcm_uframes_t frames_to_read;
 	uint8_t *buff;
@@ -579,10 +666,10 @@ static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
 	}
 
 	frame_size = areas->step / 8;
-	if ((data->count + size * frame_size) <= cfg.pkt_len)
+	if ((data->count + size * frame_size) <= data->link_mtu)
 		frames_to_read = size;
 	else
-		frames_to_read = (cfg.pkt_len - data->count) / frame_size;
+		frames_to_read = (data->link_mtu - data->count) / frame_size;
 
 	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
 
@@ -593,12 +680,12 @@ static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
 
 	/* Remember we have some frames in the pipe now */
 	data->count += frames_to_read * frame_size;
-	if (data->count != cfg.pkt_len) {
+	if (data->count != data->link_mtu) {
 		ret = frames_to_read;
 		goto done;
 	}
 
-	rsend = send(data->stream.fd, data->buffer, cfg.pkt_len,
+	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
 			io->nonblock ? MSG_DONTWAIT : 0);
 	if (rsend > 0) {
 		/* Reset count pointer */
@@ -710,7 +797,7 @@ static snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
 			frames_to_read = (a2dp->codesize - data->count) / frame_size;
 
 		DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
-		DBG("a2dp.count=%d cfg.pkt_len=%d", a2dp->count, data->cfg.pkt_len);
+		DBG("a2dp.count=%d data.link_mtu=%d", a2dp->count, data->link_mtu);
 
 		/* FIXME: If state is not streaming then return */
 
@@ -747,10 +834,10 @@ static snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
 				written, a2dp->count);
 
 		/* No space left for another frame then send */
-		if (a2dp->count + written >= data->cfg.pkt_len) {
+		if (a2dp->count + written >= data->link_mtu) {
 			avdtp_write(data);
-			DBG("sending packet %d, count %d, pkt_len %u", c,
-					old_count, data->cfg.pkt_len);
+			DBG("sending packet %d, count %d, link_mtu %u", c,
+					old_count, data->link_mtu);
 		}
 
 		ret += frames_to_read;
@@ -791,7 +878,6 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
 	.stop			= bluetooth_playback_stop,
 	.pointer		= bluetooth_pointer,
 	.close			= bluetooth_close,
-	.hw_params		= bluetooth_hsp_hw_params,
 	.prepare		= bluetooth_prepare,
 	.transfer		= bluetooth_hsp_write,
 	.poll_descriptors	= bluetooth_playback_poll_descriptors,
@@ -804,7 +890,6 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
 	.stop			= bluetooth_stop,
 	.pointer		= bluetooth_pointer,
 	.close			= bluetooth_close,
-	.hw_params		= bluetooth_hsp_hw_params,
 	.prepare		= bluetooth_prepare,
 	.transfer		= bluetooth_hsp_read,
 	.poll_descriptors	= bluetooth_poll_descriptors,
@@ -841,7 +926,6 @@ static snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
 static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
-	struct ipc_data_cfg cfg = data->cfg;
 	snd_pcm_access_t access_list[] = {
 		SND_PCM_ACCESS_RW_INTERLEAVED,
 		/* Mmap access is really useless fo this driver, but we
@@ -852,7 +936,7 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
 	unsigned int format_list[] = {
 		SND_PCM_FORMAT_S16_LE
 	};
-	int err, channels;
+	int err;
 
 	/* access type */
 	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
@@ -867,21 +951,20 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
 		return err;
 
 	/* supported channels */
-	channels = cfg.mode == CFG_MODE_MONO ? 1 : 2;
 	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
-							channels, channels);
+							1, 1);
 	if (err < 0)
 		return err;
 
 	/* supported rate */
 	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
-							cfg.rate, cfg.rate);
+							8000, 8000);
 	if (err < 0)
 		return err;
 
 	/* supported block size */
 	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
-						cfg.pkt_len, cfg.pkt_len);
+						data->link_mtu, data->link_mtu);
 	if (err < 0)
 		return err;
 
@@ -896,7 +979,7 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
 static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
-	struct ipc_data_cfg cfg = data->cfg;
+	struct bluetooth_a2dp *a2dp = &data->a2dp;
 	snd_pcm_access_t access_list[] = {
 		SND_PCM_ACCESS_RW_INTERLEAVED,
 		/* Mmap access is really useless fo this driver, but we
@@ -907,10 +990,12 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
 	unsigned int format_list[] = {
 		SND_PCM_FORMAT_S16_LE
 	};
+	unsigned int rate_list[4];
+	unsigned int rate_count;
+	int err, min_channels, max_channels;
 	unsigned int period_list[] = {
 		4096, /* 23/46ms (stereo/mono 16bit at 44.1kHz) */
 	};
-	int err, channels;
 
 	/* access type */
 	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
@@ -925,15 +1010,18 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
 		return err;
 
 	/* supported channels */
-	channels = cfg.mode == CFG_MODE_MONO ? 1 : 2;
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
-							channels, channels);
-	if (err < 0)
-		return err;
+	if (a2dp->sbc_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+		min_channels = 1;
+	else
+		min_channels = 2;
 
-	/* supported rate */
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
-							cfg.rate, cfg.rate);
+	if (a2dp->sbc_capabilities.channel_mode & (~BT_A2DP_CHANNEL_MODE_MONO))
+		max_channels = 2;
+	else
+		max_channels = 1;
+
+	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
+							min_channels, max_channels);
 	if (err < 0)
 		return err;
 
@@ -949,96 +1037,44 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
 	if (err < 0)
 		return err;
 
-	return 0;
-}
-
-static int bluetooth_recvmsg_fd(struct bluetooth_data *data)
-{
-	char cmsg_b[CMSG_SPACE(sizeof(int))], m;
-	int err, ret;
-	struct iovec iov = { &m, sizeof(m) };
-	struct msghdr msgh;
-	struct cmsghdr *cmsg;
-
-	memset(&msgh, 0, sizeof(msgh));
-	msgh.msg_iov = &iov;
-	msgh.msg_iovlen = 1;
-	msgh.msg_control = &cmsg_b;
-	msgh.msg_controllen = CMSG_LEN(sizeof(int));
-
-	ret = recvmsg(data->server.fd, &msgh, 0);
-	if (ret < 0) {
-		err = errno;
-		SNDERR("Unable to receive fd: %s (%d)", strerror(err), err);
-		return -err;
+	/* supported rates */
+	rate_count = 0;
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) {
+		rate_list[rate_count] = 16000;
+		rate_count++;
 	}
 
-	/* Receive auxiliary data in msgh */
-	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
-			cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
-		if (cmsg->cmsg_level == SOL_SOCKET
-				&& cmsg->cmsg_type == SCM_RIGHTS) {
-			data->stream.fd = (*(int *) CMSG_DATA(cmsg));
-			DBG("stream_fd=%d", data->stream.fd);
-			return 0;
-		}
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) {
+		rate_list[rate_count] = 32000;
+		rate_count++;
 	}
 
-	return -EINVAL;
-}
-
-static int bluetooth_a2dp_init(struct bluetooth_data *data,
-				struct ipc_codec_sbc *sbc)
-{
-	struct bluetooth_a2dp *a2dp = &data->a2dp;
-	struct ipc_data_cfg *cfg = &data->cfg;
-
-	if (cfg == NULL) {
-		SNDERR("Error getting codec parameters");
-		return -1;
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) {
+		rate_list[rate_count] = 44100;
+		rate_count++;
 	}
 
-	if (cfg->codec != CFG_CODEC_SBC)
-		return -1;
-
-	/* FIXME: init using flags? */
-	sbc_init(&a2dp->sbc, 0);
-	a2dp->sbc.rate = cfg->rate;
-	a2dp->sbc.channels = cfg->mode == CFG_MODE_MONO ? 1 : 2;
-	if (cfg->mode == CFG_MODE_MONO || cfg->mode == CFG_MODE_JOINT_STEREO)
-		a2dp->sbc.joint = 1;
-	a2dp->sbc.allocation = sbc->allocation;
-	a2dp->sbc.subbands = sbc->subbands;
-	a2dp->sbc.blocks = sbc->blocks;
-	a2dp->sbc.bitpool = sbc->bitpool;
-	a2dp->codesize = a2dp->sbc.subbands * a2dp->sbc.blocks *
-						a2dp->sbc.channels * 2;
-	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) {
+		rate_list[rate_count] = 48000;
+		rate_count++;
+	}
 
-	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
-		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
-		a2dp->sbc.bitpool);
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
+							rate_count, rate_list);
+	if (err < 0)
+		return err;
 
 	return 0;
 }
 
-static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
-				snd_config_t *conf)
+static int bluetooth_parse_config(snd_config_t *conf,
+				struct bluetooth_alsa_config *bt_config)
 {
-	struct ipc_data_cfg *cfg = (void *) pkt->data;
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
 	snd_config_iterator_t i, next;
 	const char *addr, *pref;
 	const char *mode, *allocation, *rate, *subbands, *blocks, *bitpool;
 
-	switch (stream) {
-	case SND_PCM_STREAM_PLAYBACK:
-		cfg->fd_opt = CFG_FD_OPT_WRITE;
-		break;
-	case SND_PCM_STREAM_CAPTURE:
-		cfg->fd_opt = CFG_FD_OPT_READ;
-		break;
-	}
+	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
 
 	snd_config_for_each(i, next, conf) {
 		snd_config_t *n = snd_config_iterator_entry(i);
@@ -1056,7 +1092,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			strncpy(pkt->device, addr, 18);
+			bt_config->has_device = 1;
+			strncpy(bt_config->device, addr, 18);
 			continue;
 		}
 
@@ -1066,14 +1103,18 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			if (strcmp(pref, "auto") == 0)
-				pkt->role = PKT_ROLE_AUTO;
-			else if (strcmp(pref, "voice") == 0 ||
+			if (strcmp(pref, "auto") == 0) {
+				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
+				bt_config->has_transport = 1;
+			} else if (strcmp(pref, "voice") == 0 ||
 						strcmp(pref, "hfp") == 0) {
-				pkt->role = PKT_ROLE_VOICE;
+				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
+				bt_config->has_transport = 1;
 			} else if (strcmp(pref, "hifi") == 0 ||
-						strcmp(pref, "a2dp") == 0)
-				pkt->role = PKT_ROLE_HIFI;
+						strcmp(pref, "a2dp") == 0) {
+				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+				bt_config->has_transport = 1;
+			}
 			continue;
 		}
 
@@ -1083,7 +1124,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			cfg->rate = atoi(rate);
+			bt_config->rate = atoi(rate);
+			bt_config->has_rate = 1;
 			continue;
 		}
 
@@ -1093,16 +1135,22 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			if (strcmp(pref, "auto") == 0)
-				cfg->mode = CFG_MODE_AUTO;
-			else if (strcmp(pref, "mono") == 0)
-				cfg->mode = CFG_MODE_MONO;
-			else if (strcmp(pref, "dual") == 0)
-				cfg->mode = CFG_MODE_DUAL_CHANNEL;
-			else if (strcmp(pref, "stereo") == 0)
-				cfg->mode = CFG_MODE_STEREO;
-			else if (strcmp(pref, "joint") == 0)
-				cfg->mode = CFG_MODE_JOINT_STEREO;
+			if (strcmp(pref, "auto") == 0) {
+				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO;
+				bt_config->has_channel_mode = 1;
+			} else if (strcmp(pref, "mono") == 0) {
+				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+				bt_config->has_channel_mode = 1;
+			} else if (strcmp(pref, "dual") == 0) {
+				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+				bt_config->has_channel_mode = 1;
+			} else if (strcmp(pref, "stereo") == 0) {
+				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+				bt_config->has_channel_mode = 1;
+			} else if (strcmp(pref, "joint") == 0) {
+				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+				bt_config->has_channel_mode = 1;
+			}
 			continue;
 		}
 
@@ -1112,12 +1160,16 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			if (strcmp(pref, "auto") == 0)
-				sbc->allocation = CFG_ALLOCATION_AUTO;
-			else if (strcmp(pref, "loudness") == 0)
-				sbc->allocation = CFG_ALLOCATION_LOUDNESS;
-			else if (strcmp(pref, "snr") == 0)
-				sbc->allocation = CFG_ALLOCATION_SNR;
+			if (strcmp(pref, "auto") == 0) {
+				bt_config->allocation_method = BT_A2DP_ALLOCATION_AUTO;
+				bt_config->has_allocation_method = 1;
+			} else if (strcmp(pref, "loudness") == 0) {
+				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
+				bt_config->has_allocation_method = 1;
+			} else if (strcmp(pref, "snr") == 0) {
+				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
+				bt_config->has_allocation_method = 1;
+			}
 			continue;
 		}
 
@@ -1127,7 +1179,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			sbc->subbands = atoi(subbands);
+			bt_config->subbands = atoi(subbands);
+			bt_config->has_subbands = 1;
 			continue;
 		}
 
@@ -1137,7 +1190,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			sbc->blocks = atoi(blocks);
+			bt_config->block_length = atoi(blocks);
+			bt_config->has_block_length = 1;
 			continue;
 		}
 
@@ -1147,7 +1201,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 				return -EINVAL;
 			}
 
-			sbc->bitpool = atoi(bitpool);
+			bt_config->bitpool = atoi(bitpool);
+			bt_config->has_bitpool = 1;
 			continue;
 		}
 
@@ -1155,139 +1210,82 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_pcm_stream_t stream,
 		return -EINVAL;
 	}
 
-	pkt->length = sizeof(*cfg) + sizeof(*sbc);
-	pkt->type = PKT_TYPE_CFG_REQ;
-	pkt->error = PKT_ERROR_NONE;
-
 	return 0;
 }
 
-static int bluetooth_cfg(struct bluetooth_data *data, snd_pcm_stream_t stream,
-				snd_config_t *conf)
+static int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
 {
-	int ret, total;
-	char buf[IPC_MTU];
-	struct ipc_packet *pkt = (void *) buf;
-	struct ipc_data_cfg *cfg = (void *) pkt->data;
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
-
-	DBG("Sending PKT_TYPE_CFG_REQ...");
-
-	memset(buf, 0, sizeof(buf));
-
-	ret = bluetooth_cfg_init(pkt, stream, conf);
-	if (ret < 0)
-		return -ret;
-
-	ret = send(data->server.fd, pkt, sizeof(*pkt) + pkt->length, 0);
-	if (ret < 0)
-		return -errno;
-	else if (ret == 0)
-		return -EIO;
-
-	DBG("OK - %d bytes sent. Waiting for response...", ret);
-
-	memset(buf, 0, sizeof(buf));
-
-	ret = recv(data->server.fd, buf, sizeof(*pkt) + sizeof(*cfg), 0);
-	if (ret < 0)
-		return -errno;
-	else if (ret == 0)
-		return -EIO;
-
-	total = ret;
-
-	if (pkt->type != PKT_TYPE_CFG_RSP) {
-		SNDERR("Unexpected packet type %d received", pkt->type);
-		return -EINVAL;
-	}
-
-	if (pkt->error != PKT_ERROR_NONE) {
-		SNDERR("Error %d while configuring device", pkt->error);
-		return -pkt->error;
-	}
-
-	if (cfg->codec != CFG_CODEC_SBC)
-		goto done;
-
-	ret = recv(data->server.fd, sbc, sizeof(*sbc), 0);
-	if (ret < 0)
-		return -errno;
-	else if (ret == 0)
-		return -EIO;
-
-	total += ret;
-
-done:
-	DBG("OK - %d bytes received", total);
-
-	if (pkt->length != (total - sizeof(struct ipc_packet))) {
-		SNDERR("Error while configuring device: packet size doesn't match");
-		return -EINVAL;
+	int err;
+	DBG("sending %s", bt_audio_strmsg[msg->msg_type]);
+	if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
+		err = 0;
+	} else {
+		err = -errno;
+		SNDERR("Error sending data to audio service: %s(%d)", strerror(errno), errno);
 	}
+	return err;
+}
 
-	memcpy(&data->cfg, cfg, sizeof(*cfg));
-
-	DBG("Device configuration:");
-
-	DBG("\n\tfd=%d\n\tfd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u",
-			data->stream.fd, data->cfg.fd_opt, data->cfg.pkt_len,
-			data->cfg.sample_size, data->cfg.rate);
-
-	if (data->cfg.codec == CFG_CODEC_SBC) {
-		ret = bluetooth_a2dp_init(data, sbc);
-		if (ret < 0)
-			return ret;
+static int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
+{
+	int err;
+	DBG("trying to receive msg from audio service...");
+	if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
+		if (inmsg->msg_type <= BT_MSG_MAX) {
+			DBG("Received %s", bt_audio_strmsg[inmsg->msg_type]);
+			err = 0;
+		} else {
+			err = -EINVAL;
+			SNDERR("Bogus message type %d "
+					"received from audio service",
+					inmsg->msg_type);
+		}
+	} else {
+		err = -errno;
+		SNDERR("Error receiving data from audio service: %s(%d)",
+					strerror(errno), errno);
 	}
+	return err;
+}
 
-	ret = bluetooth_recvmsg_fd(data);
-	if (ret < 0)
-		return ret;
-
-	if (data->stream.fd == -1) {
-		SNDERR("Error while configuring device: could not acquire audio socket");
-		return -EINVAL;
+static int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg,
+				int expected_type)
+{
+	int err = audioservice_recv(sk, outmsg);
+	if (err == 0) {
+		if (outmsg->msg_type != expected_type) {
+			err = -EINVAL;
+			SNDERR("Bogus message %s received while "
+					"%s was expected",
+					bt_audio_strmsg[outmsg->msg_type],
+					bt_audio_strmsg[expected_type]);
+		}
 	}
-
-	/* It is possible there is some outstanding
-	data in the pipe - we have to empty it */
-	while (recv(data->stream.fd, data->buffer, data->cfg.pkt_len,
-				MSG_DONTWAIT) > 0);
-
-	memset(data->buffer, 0, sizeof(data->buffer));
-
-	return 0;
+	return err;
 }
 
 static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,
 				snd_config_t *conf)
 {
 	int sk, err;
-	struct sockaddr_un addr = {
-		AF_UNIX, IPC_SOCKET_NAME
-	};
-
-	if (!data)
-		return -EINVAL;
+	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_getcapabilities_req *getcaps_req = (void*) buf;
+	struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf;
 
 	memset(data, 0, sizeof(struct bluetooth_data));
 
+	err = bluetooth_parse_config(conf, alsa_conf);
+	if (err < 0)
+		return err;
+
 	data->server.fd = -1;
 	data->stream.fd = -1;
 
-	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
-	if (sk < 0) {
-		err = errno;
-		SNDERR("Cannot open socket: %s (%d)", strerror(err), err);
-		return -err;
-	}
-
-	DBG("Connecting to address: %s", addr.sun_path + 1);
-	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		err = errno;
-		SNDERR("Connection fail", strerror(err), err);
-		close(sk);
-		return -err;
+	sk = bt_audio_service_open();
+	if(sk <= 0) {
+		err = -errno;
+		goto failed;
 	}
 
 	data->server.fd = sk;
@@ -1296,14 +1294,56 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,
 	data->pipefd[0] = -1;
 	data->pipefd[1] = -1;
 
-	if (pipe(data->pipefd) < 0)
-		return -errno;
-	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0)
-		return -errno;
-	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0)
-		return -errno;
+	if (pipe(data->pipefd) < 0) {
+		err = -errno;
+		goto failed;
+	}
+	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
+		err = -errno;
+		goto failed;
+	}
+	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
+		err = -errno;
+		goto failed;
+	}
+
+	memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+	getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ;
+	strncpy(getcaps_req->device, alsa_conf->device, 18);
+	if (alsa_conf->has_transport)
+		getcaps_req->transport = alsa_conf->transport;
+	else
+		getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
+
+	getcaps_req->access_mode = (stream == SND_PCM_STREAM_PLAYBACK ?
+			BT_CAPABILITIES_ACCESS_MODE_WRITE :
+			BT_CAPABILITIES_ACCESS_MODE_READ);
+
+	err = audioservice_send(data->server.fd, &getcaps_req->h);
+	if (err < 0)
+		goto failed;
+
+	err = audioservice_expect(data->server.fd, &getcaps_rsp->h, BT_GETCAPABILITIES_RSP);
+	if (err < 0)
+		goto failed;
+
+	if (getcaps_rsp->posix_errno != 0) {
+		SNDERR("BT_GETCAPABILITIES failed : %s(%d)",
+					strerror(getcaps_rsp->posix_errno),
+					getcaps_rsp->posix_errno);
+		return -getcaps_rsp->posix_errno;
+	}
+
+	data->transport = getcaps_rsp->transport;
+	data->link_mtu = getcaps_rsp->link_mtu;
+	if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
+		data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities;
 
-	return bluetooth_cfg(data, stream, conf);
+	return 0;
+
+failed:
+	bt_audio_service_close(sk);
+	return err;
 }
 
 SND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
@@ -1329,7 +1369,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
 	data->io.mmap_rw = 0; /* No direct mmap communication */
 	data->io.private_data = data;
 
-	if (data->cfg.codec == CFG_CODEC_SBC)
+	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
 		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
 			&bluetooth_a2dp_playback :
 			&bluetooth_a2dp_capture;
@@ -1342,7 +1382,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
 	if (err < 0)
 		goto error;
 
-	if (data->cfg.codec == CFG_CODEC_SBC)
+	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
 		err = bluetooth_a2dp_hw_constraint(&data->io);
 	else
 		err = bluetooth_hsp_hw_constraint(&data->io);
diff --git a/audio/unix.c b/audio/unix.c
index 71eb570..f7211e2 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -79,7 +79,8 @@ struct unix_client {
 		struct headset_data hs;
 	} d;
 	int sock;
-	int fd_opt;
+	int access_mode;
+	int data_fd; /* To be deleted once two phase configuration is fully implemented */
 	unsigned int req_id;
 	unsigned int cb_id;
 	gboolean (*cancel_stream) (struct device *dev, unsigned int id);
@@ -89,6 +90,11 @@ static GSList *clients = NULL;
 
 static int unix_sock = -1;
 
+static void unix_ipc_sendmsg(struct unix_client *client,
+					const bt_audio_msg_header_t *msg);
+
+static void send_getcapabilities_rsp_error(struct unix_client *client, int err);
+
 static void client_free(struct unix_client *client)
 {
 	struct a2dp_data *a2dp;
@@ -121,7 +127,7 @@ static void client_free(struct unix_client *client)
 
 /* Pass file descriptor through local domain sockets (AF_LOCAL, formerly AF_UNIX)
 and the sendmsg() system call with the cmsg_type field of a "struct cmsghdr" set
-to SCM_RIGHTS and the data being an integer value equal to the handle of the 
+to SCM_RIGHTS and the data being an integer value equal to the handle of the
 file descriptor to be passed.*/
 static int unix_sendmsg_fd(int sock, int fd)
 {
@@ -193,77 +199,29 @@ static void stream_state_changed(struct avdtp_stream *stream,
 	}
 }
 
-static int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd)
-{
-	char buf[IPC_MTU];
-	struct ipc_packet *pkt = (void *) buf;
-	int len, codec_len;
-
-	memset(buf, 0, sizeof(buf));
-
-	pkt->type = PKT_TYPE_CFG_RSP;
-
-	if (!cfg) {
-		pkt->error = EINVAL;
-		len = send(sock, pkt, sizeof(struct ipc_packet), 0);
-		if (len < 0)
-			error("send: %s (%d)", strerror(errno), errno);
-		return len;
-	}
-
-	debug("fd=%d, fd_opt=%u, pkt_len=%u, sample_size=%u, rate=%u",
-						fd, cfg->fd_opt, cfg->pkt_len,
-						cfg->sample_size, cfg->rate);
-
-	if (cfg->codec == CFG_CODEC_SBC)
-		codec_len = sizeof(struct ipc_codec_sbc);
-	else
-		codec_len = 0;
-
-	pkt->error = PKT_ERROR_NONE;
-	pkt->length = sizeof(struct ipc_data_cfg) + codec_len;
-	memcpy(pkt->data, cfg, pkt->length);
-
-	len = sizeof(struct ipc_packet) + pkt->length;
-	len = send(sock, pkt, len, 0);
-	if (len < 0)
-		error("Error %s(%d)", strerror(errno), errno);
-
-	debug("%d bytes sent", len);
-
-	if (fd != -1) {
-		len = unix_sendmsg_fd(sock, fd);
-		if (len < 0)
-			error("Error %s(%d)", strerror(errno), errno);
-		debug("%d bytes sent", len);
-	}
-
-	return 0;
-}
-
 static void headset_setup_complete(struct device *dev, void *user_data)
 {
 	struct unix_client *client = user_data;
-	struct ipc_data_cfg cfg;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_getcapabilities_rsp *rsp = (void *) buf;
 	struct headset_data *hs = &client->d.hs;
-	int fd;
 
 	client->req_id = 0;
 
 	if (!dev) {
-		unix_send_cfg(client->sock, NULL, -1);
+		send_getcapabilities_rsp_error(client, EIO);
 		client->dev = NULL;
 		return;
 	}
 
-	switch (client->fd_opt) {
-	case CFG_FD_OPT_READ:
+	switch (client->access_mode) {
+	case BT_CAPABILITIES_ACCESS_MODE_READ:
 		hs->lock = HEADSET_LOCK_READ;
 		break;
-	case CFG_FD_OPT_WRITE:
+	case BT_CAPABILITIES_ACCESS_MODE_WRITE:
 		hs->lock = HEADSET_LOCK_WRITE;
 		break;
-	case CFG_FD_OPT_READWRITE:
+	case BT_CAPABILITIES_ACCESS_MODE_READWRITE:
 		hs->lock = HEADSET_LOCK_READ | HEADSET_LOCK_WRITE;
 		break;
 	default:
@@ -273,23 +231,22 @@ static void headset_setup_complete(struct device *dev, void *user_data)
 
 	if (!headset_lock(dev, hs->lock)) {
 		error("Unable to lock headset");
-		unix_send_cfg(client->sock, NULL, -1);
+		send_getcapabilities_rsp_error(client, EIO);
 		client->dev = NULL;
 		return;
 	}
 
-	memset(&cfg, 0, sizeof(cfg));
+	memset(buf, 0, sizeof(buf));
 
-	cfg.fd_opt = client->fd_opt;
-	cfg.codec = CFG_CODEC_SCO;
-	cfg.mode = CFG_MODE_MONO;
-	cfg.pkt_len = 48;
-	cfg.sample_size = 2;
-	cfg.rate = 8000;
+	rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
+	rsp->transport  = BT_CAPABILITIES_TRANSPORT_SCO;
+	rsp->access_mode = client->access_mode;
+	rsp->link_mtu = 48;
+	rsp->sampling_rate = 8000;
 
-	fd = headset_get_sco_fd(dev);
+	client->data_fd = headset_get_sco_fd(dev);
 
-	unix_send_cfg(client->sock, &cfg, fd);
+	unix_ipc_sendmsg(client, &rsp->h);
 }
 
 static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
@@ -297,17 +254,16 @@ static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
 					void *user_data, struct avdtp_error *err)
 {
 	struct unix_client *client = user_data;
-	char buf[sizeof(struct ipc_data_cfg) + sizeof(struct ipc_codec_sbc)];
-	struct ipc_data_cfg *cfg = (void *) buf;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_getcapabilities_rsp *rsp = (void *) buf;
 	struct avdtp_service_capability *cap;
 	struct avdtp_media_codec_capability *codec_cap;
 	struct sbc_codec_cap *sbc_cap;
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
 	struct a2dp_data *a2dp = &client->d.a2dp;
-	int fd;
 	uint16_t imtu, omtu;
 	GSList *caps;
 
+	memset(buf, 0, sizeof(buf));
 	client->req_id = 0;
 
 	if (!stream)
@@ -321,7 +277,7 @@ static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
 	a2dp->sep = sep;
 	a2dp->stream = stream;
 
-	if (!avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, &caps)) {
+	if (!avdtp_stream_get_transport(stream, &client->data_fd, &imtu, &omtu, &caps)) {
 		error("Unable to get stream transport");
 		goto failed;
 	}
@@ -340,66 +296,26 @@ static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
 		goto failed;
 	}
 
+	rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
+	rsp->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+	client->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
+	rsp->access_mode = client->access_mode;
 	/* FIXME: Use imtu when fd_opt is CFG_FD_OPT_READ */
-	cfg->pkt_len = omtu;
-	cfg->fd_opt = CFG_FD_OPT_WRITE;
+	rsp->link_mtu = omtu;
 
 	sbc_cap = (void *) codec_cap;
-	cfg->sample_size = 2;
-
-	switch (sbc_cap->channel_mode) {
-	case A2DP_CHANNEL_MODE_MONO:
-		cfg->mode = CFG_MODE_MONO;
-		break;
-	case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
-		cfg->mode = CFG_MODE_DUAL_CHANNEL;
-		break;
-	case A2DP_CHANNEL_MODE_STEREO:
-		cfg->mode = CFG_MODE_STEREO;
-		break;
-	case A2DP_CHANNEL_MODE_JOINT_STEREO:
-		cfg->mode = CFG_MODE_JOINT_STEREO;
-		break;
-	}
-
-	switch (sbc_cap->frequency) {
-	case A2DP_SAMPLING_FREQ_16000:
-		cfg->rate = 16000;
-		break;
-	case A2DP_SAMPLING_FREQ_32000:
-		cfg->rate = 32000;
-		break;
-	case A2DP_SAMPLING_FREQ_44100:
-		cfg->rate = 44100;
-		break;
-	case A2DP_SAMPLING_FREQ_48000:
-		cfg->rate = 48000;
-		break;
-	}
-
-	cfg->codec = CFG_CODEC_SBC;
-	sbc->allocation = sbc_cap->allocation_method == A2DP_ALLOCATION_SNR ?
-								0x01 : 0x00;
-	sbc->subbands = sbc_cap->subbands == A2DP_SUBBANDS_4 ? 4 : 8;
-
-	switch (sbc_cap->block_length) {
-	case A2DP_BLOCK_LENGTH_4:
-		sbc->blocks = 4;
-		break;
-	case A2DP_BLOCK_LENGTH_8:
-		sbc->blocks = 8;
-		break;
-	case A2DP_BLOCK_LENGTH_12:
-		sbc->blocks = 12;
-		break;
-	case A2DP_BLOCK_LENGTH_16:
-		sbc->blocks = 16;
-		break;
-	}
 
-	sbc->bitpool = sbc_cap->max_bitpool;
+	/* assignations below are ok as soon as newipc.h and a2dp.h are kept in sync */
+	/* However it is not possible to cast a struct to another due to endianess issues */
+	rsp->sbc_capabilities.channel_mode = sbc_cap->channel_mode;
+	rsp->sbc_capabilities.frequency = sbc_cap->frequency;
+	rsp->sbc_capabilities.allocation_method = sbc_cap->allocation_method;
+	rsp->sbc_capabilities.subbands = sbc_cap->subbands;
+	rsp->sbc_capabilities.block_length = sbc_cap->block_length;
+	rsp->sbc_capabilities.min_bitpool = sbc_cap->min_bitpool;
+	rsp->sbc_capabilities.max_bitpool = sbc_cap->max_bitpool;
 
-	unix_send_cfg(client->sock, cfg, fd);
+	unix_ipc_sendmsg(client, &rsp->h);
 
 	client->cb_id = avdtp_stream_add_cb(session, stream,
 						stream_state_changed, client);
@@ -412,7 +328,7 @@ failed:
 		a2dp_sep_unlock(a2dp->sep, a2dp->session);
 		a2dp->sep = NULL;
 	}
-	unix_send_cfg(client->sock, NULL, -1);
+	send_getcapabilities_rsp_error(client, EIO);
 
 	avdtp_unref(a2dp->session);
 
@@ -469,7 +385,7 @@ static void create_stream(struct device *dev, struct unix_client *client)
 	return;
 
 failed:
-	unix_send_cfg(client->sock, NULL, -1);
+	send_getcapabilities_rsp_error(client, EIO);
 }
 
 static void create_cb(struct device *dev, void *user_data)
@@ -477,135 +393,58 @@ static void create_cb(struct device *dev, void *user_data)
 	struct unix_client *client = user_data;
 
 	if (!dev)
-		unix_send_cfg(client->sock, NULL, -1);
+		send_getcapabilities_rsp_error(client, EIO);
 	else
 		create_stream(dev, client);
 }
 
-static int cfg_to_caps(struct ipc_data_cfg *cfg, struct sbc_codec_cap *sbc_cap)
+static void unix_ipc_sendmsg(struct unix_client *client,
+					const bt_audio_msg_header_t *msg)
 {
-	struct ipc_codec_sbc *sbc = (void *) cfg->data;
-
-	memset(sbc_cap, 0, sizeof(struct sbc_codec_cap));
-
-	sbc_cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
-	sbc_cap->cap.media_codec_type = A2DP_CODEC_SBC;
-
-	switch (cfg->rate) {
-	case 48000:
-		sbc_cap->frequency = A2DP_SAMPLING_FREQ_48000;
-		break;
-	case 44100:
-		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100;
-		break;
-	case 32000:
-		sbc_cap->frequency = A2DP_SAMPLING_FREQ_32000;
-		break;
-	case 16000:
-		sbc_cap->frequency = A2DP_SAMPLING_FREQ_16000;
-		break;
-	default:
-		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100;
-		break;
-	}
-
-	switch (cfg->mode) {
-	case CFG_MODE_MONO:
-		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_MONO;
-		break;
-	case CFG_MODE_DUAL_CHANNEL:
-		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;
-		break;
-	case CFG_MODE_STEREO:
-		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;
-		break;
-	case CFG_MODE_JOINT_STEREO:
-		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
-		break;
-	default:
-		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
-		break;
-	}
-
-	switch (sbc->allocation) {
-	case CFG_ALLOCATION_LOUDNESS:
-		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
-		break;
-	case CFG_ALLOCATION_SNR:
-		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
-		break;
-	default:
-		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
-		break;
-	}
-
-	switch (sbc->subbands) {
-	case 8:
-		sbc_cap->subbands = A2DP_SUBBANDS_8;
-		break;
-	case 4:
-		sbc_cap->subbands = A2DP_SUBBANDS_4;
-		break;
-	default:
-		sbc_cap->subbands = A2DP_SUBBANDS_8;
-		break;
-	}
-
-	switch (sbc->blocks) {
-	case 16:
-		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16;
-		break;
-	case 12:
-		sbc_cap->block_length = A2DP_BLOCK_LENGTH_12;
-		break;
-	case 8:
-		sbc_cap->block_length = A2DP_BLOCK_LENGTH_8;
-		break;
-	case 4:
-		sbc_cap->block_length = A2DP_BLOCK_LENGTH_4;
-		break;
-	default:
-		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16;
-		break;
+	info("Audio API: sending %s", bt_audio_strmsg[msg->msg_type]);
+	if (send(client->sock, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) < 0) {
+		error("Error %s(%d)", strerror(errno), errno);
 	}
+}
 
-	if (sbc->bitpool != 0) {
-		if (sbc->bitpool > 250)
-			return -EINVAL;
+static void send_getcapabilities_rsp_error(struct unix_client *client, int err)
+{
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_getcapabilities_rsp *rsp = (void *) buf;
 
-		sbc_cap->min_bitpool = sbc->bitpool;
-		sbc_cap->max_bitpool = sbc->bitpool;
-	}
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
+	rsp->posix_errno = err;
 
-	return 0;
+	unix_ipc_sendmsg(client, &rsp->h);
 }
 
-static void cfg_event(struct unix_client *client, struct ipc_packet *pkt, int len)
+static void handle_getcapabilities_req(struct unix_client *client,
+					struct bt_getcapabilities_req *req)
 {
 	struct device *dev;
 	bdaddr_t bdaddr;
-	struct ipc_data_cfg *cfg = (void *) pkt->data;
-	struct sbc_codec_cap sbc_cap;
 
-	str2ba(pkt->device, &bdaddr);
+	str2ba(req->device, &bdaddr);
+
+	if (!req->access_mode) {
+		send_getcapabilities_rsp_error(client, EINVAL);
+		return;
+	}
 
-	client->fd_opt = cfg->fd_opt;
+	client->access_mode = req->access_mode;
 
 	if (client->interface) {
 		g_free(client->interface);
 		client->interface = NULL;
 	}
 
-	if (pkt->role == PKT_ROLE_VOICE)
+	if (req->transport == BT_CAPABILITIES_TRANSPORT_SCO)
 		client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
-	else if (pkt->role == PKT_ROLE_HIFI)
+	else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
 		client->interface = g_strdup(AUDIO_SINK_INTERFACE);
 
-	if (cfg_to_caps(cfg, &sbc_cap) < 0)
-		goto failed;
-
-	client->media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC,
-						&sbc_cap, sizeof(sbc_cap));
+	client->media_codec = 0;
 
 	if (!manager_find_device(&bdaddr, NULL, FALSE)) {
 		if (!bacmp(&bdaddr, BDADDR_ANY))
@@ -627,57 +466,80 @@ static void cfg_event(struct unix_client *client, struct ipc_packet *pkt, int le
 	return;
 
 failed:
-	unix_send_cfg(client->sock, NULL, -1);
+	send_getcapabilities_rsp_error(client, EIO);
 }
 
-static void ctl_event(struct unix_client *client,
-					struct ipc_packet *pkt, int len)
+static void handle_setconfiguration_req(struct unix_client *client,
+					struct bt_setconfiguration_req *req)
 {
+	/* FIXME: for now we just blindly assume that we receive is the
+	   only valid configuration sent.*/
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_setconfiguration_rsp *rsp = (void *) buf;
+
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_SETCONFIGURATION_RSP;
+	rsp->posix_errno = 0;
+
+	unix_ipc_sendmsg(client, &rsp->h);
 }
 
-static int reply_state(int sock, struct ipc_packet *pkt)
+static void handle_streamstart_req(struct unix_client *client,
+					struct bt_streamstart_req *req)
 {
-	struct ipc_data_state *state = (struct ipc_data_state *) pkt->data;
-	int len;
+	/* FIXME : to be really implemented */
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_streamstart_rsp *rsp = (void *) buf;
+	struct bt_datafd_ind *ind = (void *) buf;
 
-	info("status=%u", state->state);
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_STREAMSTART_RSP;
+	rsp->posix_errno = 0;
+	unix_ipc_sendmsg(client, &rsp->h);
 
-	pkt->type = PKT_TYPE_STATE_RSP;
-	pkt->length = sizeof(struct ipc_data_state);
-	pkt->error = PKT_ERROR_NONE;
+	memset(buf, 0, sizeof(buf));
+	ind->h.msg_type = BT_STREAMFD_IND;
+	unix_ipc_sendmsg(client, &ind->h);
 
-	len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_state);
-	len = send(sock, pkt, len, 0);
-	if (len < 0)
-		error("Error %s(%d)", strerror(errno), errno);
+	if (unix_sendmsg_fd(client->sock, client->data_fd) < 0)
+		error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
 
-	debug("%d bytes sent", len);
+}
 
-	return 0;
+static void handle_streamstop_req(struct unix_client *client,
+					struct bt_streamstop_req *req)
+{
+	/* FIXME : to be implemented */
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_streamstop_rsp *rsp = (void *) buf;
+
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_STREAMSTOP_RSP;
+	rsp->posix_errno = 0;
+
+	unix_ipc_sendmsg(client, &rsp->h);
 }
 
-static void state_event(struct unix_client *client,
-					struct ipc_packet *pkt, int len)
+static void handle_control_req(struct unix_client *client,
+					struct bt_control_req *req)
 {
-#if 0
-	struct ipc_data_state *state = (struct ipc_data_state *) pkt->data;
-	struct device *dev = client->dev;
+	/* FIXME: really implement that */
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_setconfiguration_rsp *rsp = (void *) buf;
 
-	if (len > sizeof(struct ipc_packet))
-		device_set_state(dev, state->state);
-	else
-		state->state = device_get_state(dev);
-#endif
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_CONTROL_RSP;
+	rsp->posix_errno = 0;
 
-	reply_state(client->sock, pkt);
+	unix_ipc_sendmsg(client, &rsp->h);
 }
 
 static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 {
-	char buf[IPC_MTU];
-	struct ipc_packet *pkt = (void *) buf;
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	bt_audio_msg_header_t *msghdr = (void *) buf;
 	struct unix_client *client = data;
-	int len, len_check;
+	int len;
 	struct a2dp_data *a2dp = &client->d.a2dp;
 	struct headset_data *hs = &client->d.hs;
 
@@ -709,31 +571,39 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 
 	memset(buf, 0, sizeof(buf));
 
-	len = recv(client->sock, buf, sizeof(buf), 0);
+	len = recv(client->sock, buf, sizeof(buf), MSG_WAITALL);
 	if (len < 0) {
 		error("recv: %s (%d)", strerror(errno), errno);
 		goto failed;
 	}
 
-	len_check = pkt->length + sizeof(struct ipc_packet);
-	if (len != len_check) {
-		error("Packet lenght doesn't match");
-		goto failed;
+	if (msghdr->msg_type <= BT_MSG_MAX) {
+		info("Audio API: received %s", bt_audio_strmsg[msghdr->msg_type]);
 	}
 
-	switch (pkt->type) {
-	case PKT_TYPE_CFG_REQ:
-		info("Package PKT_TYPE_CFG_REQ:%u", pkt->role);
-		cfg_event(client, pkt, len);
+	switch (msghdr->msg_type) {
+	case BT_GETCAPABILITIES_REQ:
+		handle_getcapabilities_req(client,
+				(struct bt_getcapabilities_req *) msghdr);
 		break;
-	case PKT_TYPE_STATE_REQ:
-		info("Package PKT_TYPE_STATE_REQ");
-		state_event(client, pkt, len);
+	case BT_SETCONFIGURATION_REQ:
+		handle_setconfiguration_req(client,
+				(struct bt_setconfiguration_req *) msghdr);
 		break;
-	case PKT_TYPE_CTL_REQ:
-		info("Package PKT_TYPE_CTL_REQ");
-		ctl_event(client, pkt, len);
+	case BT_STREAMSTART_REQ:
+		handle_streamstart_req(client,
+				(struct bt_streamstart_req *) msghdr);
 		break;
+	case BT_STREAMSTOP_REQ:
+		handle_streamstop_req(client,
+				(struct bt_streamstop_req *) msghdr);
+		break;
+	case BT_CONTROL_REQ:
+		handle_control_req(client,
+				(struct bt_control_req *) msghdr);
+		break;
+	default:
+		error("Audio API: received unexpected packet type %d", msghdr->msg_type);
 	}
 
 	return TRUE;
@@ -789,7 +659,7 @@ int unix_init(void)
 {
 	GIOChannel *io;
 	struct sockaddr_un addr = {
-		AF_UNIX, IPC_SOCKET_NAME
+		AF_UNIX, BT_IPC_SOCKET_NAME
 	};
 
 	int sk, err;