All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabien Chevalier <fchevalier@silicom.fr>
To: Luiz Augusto von Dentz <luiz.dentz@gmail.com>,
	Johan Hedberg <johan.hedberg@nokia.com>,
	thiagoss <thiagossantos@gmail.com>
Cc: BlueZ development <bluez-devel@lists.sourceforge.net>,
	Brad Midgley <bmidgley@xmission.com>
Subject: [Bluez-devel] [PATCH] Audio service Newapi patchv3
Date: Wed, 31 Oct 2007 13:11:07 +0100	[thread overview]
Message-ID: <472870DB.9040204@silicom.fr> (raw)

[-- Attachment #1: Type: text/plain, Size: 149 bytes --]

All,

Please find attached an updated version of the newapi patch.
It fixes a set of coding style issues that Johan reported to me.

Cheers,

Fabien

[-- Attachment #2: newapiv3.diff --]
[-- Type: text/plain, Size: 76485 bytes --]

Index: pcm_bluetooth.c
===================================================================
--- pcm_bluetooth.c	(.../tags/20071026_1010/audio)	(révision 180)
+++ pcm_bluetooth.c	(.../branches/20071026_1010/audio)	(révision 180)
@@ -33,13 +33,13 @@
 
 #include <netinet/in.h>
 
 #include <alsa/asoundlib.h>
 #include <alsa/pcm_external.h>
 
-#include "ipc.h"
+#include "audioclient.h"
 #include "sbc.h"
 #include "rtp.h"
 
 //#define ENABLE_DEBUG
 
 #define UINT_SECS_MAX (UINT_MAX / 1000000 - 1)
@@ -64,38 +64,65 @@
 
 #ifndef SCO_RXBUFS
 #define SCO_RXBUFS 0x04
 #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 */
+	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 */
+	pthread_t hw_thread;				/* Makes virtual hw pointer move */
+	int pipefd[2];					/* Inter thread communication */
 	int stopped;
 };
 
+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);
 
 	return 0;
 }
@@ -183,78 +210,19 @@
 	}
 
 	data->hw_thread = 0;
 	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;
 	int err;
 
 	DBG("%p", io);
 
-#if 0
-	bluetooth_state(data, STATE_STREAMING);
-#endif
 	data->stopped = 0;
 
 	if (data->hw_thread)
 		return 0;
 
 	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
@@ -265,15 +233,12 @@
 static int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
 
 	DBG("%p", io);
 
-#if 0
-	bluetooth_state(data, STATE_CONNECTED);
-#endif
 	data->stopped = 1;
 
 	return 0;
 }
 
 static snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
@@ -285,23 +250,23 @@
 
 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);
 
 	if (data->hw_thread) {
 		pthread_cancel(data->hw_thread);
 		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)
 		close(data->pipefd[0]);
 
 	if (data->pipefd[1] > 0)
@@ -322,82 +287,207 @@
 }
 
 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);
 
+	/* 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 */
 		data->hw_ptr = 0;
 	else
 		/* ALSA library is really picky on the fact hw_ptr is not null.
 		 * 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;
+	
+	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
+	setconf_req->sbc_capabilities = active_capabilities;
 
-	if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
-							sizeof(t)) == 0)
-		return 0;
+	err = audioservice_send(data->server.fd, &setconf_req->h);
+	if (err < 0)
+		return err;
 
-	err = errno;
+	err = audioservice_expect(data->server.fd, &setconf_rsp->h, BT_SETCONFIGURATION_RSP);
+	if (err < 0)
+		return err;
 
-	SNDERR("%s (%d)", strerror(err), 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;
+	}
 
-	return -err;
+	/* 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,
 					struct pollfd *pfd, unsigned int space)
 {
 	struct bluetooth_data *data = io->private_data;
@@ -469,55 +559,54 @@
 
 static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
 				const snd_pcm_channel_area_t *areas,
 				snd_pcm_uframes_t offset, 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;
 
 	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
 			areas->step, areas->first, offset, size, io->nonblock);
 
 	if (data->count > 0)
 		goto proceed;
 
 	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) {
 		ret = (errno == EPIPE) ? -EIO : -errno;
 		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;
 
 done:
 	DBG("returning %lu", ret);
@@ -526,13 +615,12 @@
 
 static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
 				const snd_pcm_channel_area_t *areas,
 				snd_pcm_uframes_t offset, 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;
 	int rsend, frame_size;
 
 	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
@@ -543,32 +631,32 @@
 		if (ret == 0)
 			ret = -EPIPE;
 		goto done;
 	}
 
 	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);
 
 	/* Ready for more data */
 	buff = (uint8_t *) areas->addr +
 			(areas->first + areas->step * offset) / 8;
 	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
 
 	/* 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 */
 		data->count = 0;
 
 		ret = frames_to_read;
@@ -665,13 +753,13 @@
 	if ((data->count + size * frame_size) <= a2dp->codesize)
 		frames_to_read = size;
 	else
 		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 */
 
 	/* Ready for more data */
 	buff = (uint8_t *) areas->addr +
 				(areas->first + areas->step * offset) / 8;
@@ -692,13 +780,13 @@
 	}
 
 	data->count -= encoded;
 
 	DBG("encoded=%d  a2dp.sbc.len=%d", encoded, a2dp->sbc.len);
 
-	if (a2dp->count + a2dp->sbc.len >= data->cfg.pkt_len) {
+	if (a2dp->count + a2dp->sbc.len >= data->link_mtu) {
 		ret = avdtp_write(data);
 		if (ret < 0) {
 			if (-ret == EPIPE)
 				ret = -EIO;
 			goto done;
 		}
@@ -739,26 +827,24 @@
 
 static snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
 	.start			= bluetooth_playback_start,
 	.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,
 	.poll_revents		= bluetooth_playback_poll_revents,
 	.delay			= bluetooth_playback_delay,
 };
 
 static snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
 	.start			= bluetooth_start,
 	.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,
 	.poll_revents		= bluetooth_poll_revents,
 };
 
@@ -789,24 +875,23 @@
 
 #define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
 
 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
 		 * support it because some pieces of software out there
 		 * insist on using it */
 		SND_PCM_ACCESS_MMAP_INTERLEAVED
 	};
 	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,
 					ARRAY_NELEMS(access_list), access_list);
 	if (err < 0)
 		return err;
@@ -815,27 +900,26 @@
 	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
 					ARRAY_NELEMS(format_list), format_list);
 	if (err < 0)
 		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;
 
 	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
 									2, 200);
 	if (err < 0)
@@ -845,24 +929,25 @@
 }
 
 static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
 {
 	struct bluetooth_data *data = io->private_data;
 	struct bluetooth_a2dp *a2dp = &data->a2dp;
-	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
 		 * support it because some pieces of software out there
 		 * insist on using it */
 		SND_PCM_ACCESS_MMAP_INTERLEAVED
 	};
 	unsigned int format_list[] = {
 		SND_PCM_FORMAT_S16_LE
 	};
-	int err, channels;
+	unsigned int rate_list[4];
+	unsigned int rate_count;
+	int err, min_channels, max_channels;
 
 	/* access type */
 	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
 					ARRAY_NELEMS(access_list), access_list);
 	if (err < 0)
 		return err;
@@ -871,129 +956,80 @@
 	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
 					ARRAY_NELEMS(format_list), format_list);
 	if (err < 0)
 		return err;
 
 	/* supported channels */
-	channels = cfg.mode == CFG_MODE_MONO ? 1 : 2;
+	if (a2dp->sbc_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+		min_channels = 1;
+	else
+		min_channels = 2;
+
+	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,
-							channels, channels);
+							min_channels, max_channels);
 	if (err < 0)
 		return err;
 
-	/* supported rate */
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
-							cfg.rate, cfg.rate);
+	/* supported rates */
+	rate_count = 0;	
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) {
+		rate_list[rate_count] = 16000;		
+		rate_count++;
+	}
+	
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) {
+		rate_list[rate_count] = 32000;		
+		rate_count++;
+	}
+	
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) {
+		rate_list[rate_count] = 44100;		
+		rate_count++;
+	}
+	
+	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) {
+		rate_list[rate_count] = 48000;		
+		rate_count++;
+	}
+	
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
+							rate_count, rate_list);
 	if (err < 0)
 		return err;
 
-	/* supported block sizes:
-	 *   - lower limit is A2DP codec size
-	 *   - total buffer size is the upper limit (with two periods) */
-	err = snd_pcm_ioplug_set_param_minmax(io,
-						SND_PCM_IOPLUG_HW_PERIOD_BYTES,
-						a2dp->codesize,
-						a2dp->codesize);
-	if (err < 0)
-		return err;
+	/* supported block size */
+	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
+						512, 512);
 
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
-						2, 50);
 	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;
-	}
-
-	/* 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;
-		}
-	}
-
-	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 (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);
+	err = snd_pcm_ioplug_set_param_minmax(io,
+						SND_PCM_IOPLUG_HW_PERIODS,
+						2,
+						200);
 
-	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);
+	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);
 		const char *id;
 
 		if (snd_config_get_id(n, &id) < 0)
@@ -1005,260 +1041,264 @@
 		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
 			if (snd_config_get_string(n, &addr) < 0) {
 				SNDERR("Invalid type for %s", id);
 				return -EINVAL;
 			}
 
-			strncpy(pkt->device, addr, 18);
+			bt_config->has_device = 1;
+			strncpy(bt_config->device, addr, 18);
 			continue;
 		}
 
 		if (strcmp(id, "profile") == 0) {
 			if (snd_config_get_string(n, &pref) < 0) {
 				SNDERR("Invalid type for %s", id);
 				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;
 		}
 
 		if (strcmp(id, "rate") == 0) {
 			if (snd_config_get_string(n, &rate) < 0) {
 				SNDERR("Invalid type for %s", id);
 				return -EINVAL;
 			}
 
-			cfg->rate = atoi(rate);
+			bt_config->rate = atoi(rate);
+			bt_config->has_rate = 1;
 			continue;
 		}
 
 		if (strcmp(id, "mode") == 0) {
 			if (snd_config_get_string(n, &mode) < 0) {
 				SNDERR("Invalid type for %s", id);
 				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_MONO_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;
 		}
 
 		if (strcmp(id, "allocation") == 0) {
 			if (snd_config_get_string(n, &allocation) < 0) {
 				SNDERR("Invalid type for %s", id);
 				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;
 		}
 
 		if (strcmp(id, "subbands") == 0) {
 			if (snd_config_get_string(n, &subbands) < 0) {
 				SNDERR("Invalid type for %s", id);
 				return -EINVAL;
 			}
 
-			sbc->subbands = atoi(subbands);
+			bt_config->subbands = atoi(subbands);
+			bt_config->has_subbands = 1;
 			continue;
 		}
 
 		if (strcmp(id, "blocks") == 0) {
 			if (snd_config_get_string(n, &blocks) < 0) {
 				SNDERR("Invalid type for %s", id);
 				return -EINVAL;
 			}
 
-			sbc->blocks = atoi(blocks);
+			bt_config->block_length = atoi(blocks);
+			bt_config->has_block_length = 1;
 			continue;
 		}
 
 		if (strcmp(id, "bitpool") == 0) {
 			if (snd_config_get_string(n, &bitpool) < 0) {
 				SNDERR("Invalid type for %s", id);
 				return -EINVAL;
 			}
 
-			sbc->bitpool = atoi(bitpool);
+			bt_config->bitpool = atoi(bitpool);
+			bt_config->has_bitpool = 1;
 			continue;
 		}
 
 		SNDERR("Unknown field %s", id);
 		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;
 	data->server.events = POLLIN;
 
 	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)
 {
 	struct bluetooth_data *data;
 	int err;
@@ -1278,26 +1318,26 @@
 
 	data->io.version = SND_PCM_IOPLUG_VERSION;
 	data->io.name = "Bluetooth Audio Device";
 	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;
 	else
 		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
 			&bluetooth_hsp_playback :
 			&bluetooth_hsp_capture;
 
 	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
 	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);
 
 	if (err < 0) {
 		snd_pcm_ioplug_delete(&data->io);
Index: unix.c
===================================================================
--- unix.c	(.../tags/20071026_1010/audio)	(révision 180)
+++ unix.c	(.../branches/20071026_1010/audio)	(révision 180)
@@ -38,13 +38,13 @@
 #include <bluetooth/sdp.h>
 #include <dbus/dbus.h>
 #include <glib.h>
 
 #include "logging.h"
 #include "dbus.h"
-#include "ipc.h"
+#include "audioclient.h"
 #include "device.h"
 #include "manager.h"
 #include "avdtp.h"
 #include "a2dp.h"
 #include "headset.h"
 #include "sink.h"
@@ -76,22 +76,28 @@
 	char *interface;
 	union {
 		struct a2dp_data a2dp;
 		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);
 };
 
 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;
 
 	switch (client->type) {
 	case TYPE_SINK:
@@ -190,127 +196,78 @@
 		break;
 	default:
 		break;
 	}
 }
 
-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:
 		hs->lock = 0;
 		break;
 	}
 
 	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));
-
-	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;
+	memset(buf, 0, sizeof(buf));
 
-	fd = headset_get_sco_fd(dev);
+	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;
+	
+	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,
 					struct avdtp_stream *stream,
 					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 mtu;
 	GSList *caps;
 
+	memset(buf, 0, sizeof(buf));
+
 	client->req_id = 0;
 
 	if (!stream)
 		goto failed;
 
 	if (!a2dp_sep_lock(sep, session)) {
@@ -318,18 +275,18 @@
 		goto failed;
 	}
 
 	a2dp->sep = sep;
 	a2dp->stream = stream;
 
-	if (!avdtp_stream_get_transport(stream, &fd, &mtu, &caps)) {
+	if (!avdtp_stream_get_transport(stream, &client->data_fd, &mtu, &caps)) {
 		error("Unable to get stream transport");
 		goto failed;
 	}
 
-	cfg->pkt_len = mtu;
+	rsp->link_mtu = mtu;
 
 	for (codec_cap = NULL; caps; caps = g_slist_next(caps)) {
 		cap = caps->data;
 		if (cap->category == AVDTP_MEDIA_CODEC) {
 			codec_cap = (void *) cap->data;
 			break;
@@ -339,83 +296,45 @@
 	if (codec_cap == NULL ||
 			codec_cap->media_codec_type != A2DP_CODEC_SBC) {
 		error("Unable to find matching codec capability");
 		goto failed;
 	}
 
-	cfg->fd_opt = CFG_FD_OPT_WRITE;
+	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;
+	/* rsp->link_mtu = already set (see above) */
 
 	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;
-	}
+	/* 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;
+	/* FIXME */
+	rsp->sbc_capabilities.min_bitpool = sbc_cap->max_bitpool;
+	rsp->sbc_capabilities.max_bitpool = sbc_cap->max_bitpool;
 
-	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;
-
-	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);
 
 	return;
 
 failed:
 	error("stream setup failed");
 	if (a2dp->sep) {
 		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);
 
 	a2dp->session = NULL;
 	a2dp->stream = NULL;
 }
@@ -466,149 +385,73 @@
 	client->req_id = id;
 	client->dev = dev;
 
 	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)
 {
 	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;
-
-		sbc_cap->min_bitpool = sbc->bitpool;
-		sbc_cap->max_bitpool = sbc->bitpool;
-	}
+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;
+	
+	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);
 
-	client->fd_opt = cfg->fd_opt;
+	if (!req->access_mode) {
+		send_getcapabilities_rsp_error(client, EINVAL);
+		return;
+	}
+
+	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))
 			goto failed;
 		if (!manager_create_device(&bdaddr, create_cb, client))
 			goto failed;
@@ -624,63 +467,86 @@
 
 	create_stream(dev, client);
 
 	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;
+	
+	memset(buf, 0, sizeof(buf));
+	rsp->h.msg_type = BT_STREAMSTART_RSP;
+	rsp->posix_errno = 0;
+	unix_ipc_sendmsg(client, &rsp->h);
+	
+	memset(buf, 0, sizeof(buf));
+	ind->h.msg_type = BT_STREAMFD_IND;
+	unix_ipc_sendmsg(client, &ind->h);
 
-	info("status=%u", state->state);
+	if (unix_sendmsg_fd(client->sock, client->data_fd) < 0)
+		error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
 
-	pkt->type = PKT_TYPE_STATE_RSP;
-	pkt->length = sizeof(struct ipc_data_state);
-	pkt->error = PKT_ERROR_NONE;
-
-	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);
+}
 
-	debug("%d bytes sent", len);
+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;
 
-	return 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;
-
-	if (len > sizeof(struct ipc_packet))
-		device_set_state(dev, state->state);
-	else
-		state->state = device_get_state(dev);
-#endif
+	/* FIXME: really implement that */
+	char buf[BT_AUDIO_IPC_PACKET_SIZE];
+	struct bt_setconfiguration_rsp *rsp = (void *) buf;
+	
+	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;
 
 	if (cond & G_IO_NVAL)
 		return FALSE;
 
@@ -706,37 +572,45 @@
 			client->cancel_stream(client->dev, client->req_id);
 		goto failed;
 	}
 
 	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);
-		break;
-	case PKT_TYPE_STATE_REQ:
-		info("Package PKT_TYPE_STATE_REQ");
-		state_event(client, pkt, len);
-		break;
-	case PKT_TYPE_CTL_REQ:
-		info("Package PKT_TYPE_CTL_REQ");
-		ctl_event(client, pkt, len);
+	switch (msghdr->msg_type) {
+	case BT_GETCAPABILITIES_REQ:
+		handle_getcapabilities_req(client,
+				(struct bt_getcapabilities_req *) msghdr);		
+		break;
+	case BT_SETCONFIGURATION_REQ:
+		handle_setconfiguration_req(client,
+				(struct bt_setconfiguration_req *) msghdr);		
+		break;
+	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;
 
 failed:
 	clients = g_slist_remove(clients, client);
@@ -786,13 +660,13 @@
 }
 
 int unix_init(void)
 {
 	GIOChannel *io;
 	struct sockaddr_un addr = {
-		AF_UNIX, IPC_SOCKET_NAME
+		AF_UNIX, BT_IPC_SOCKET_NAME
 	};
 
 	int sk, err;
 
 	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
 	if (sk < 0) {
Index: audioclient.c
===================================================================
--- audioclient.c	(.../tags/20071026_1010/audio)	(révision 0)
+++ audioclient.c	(.../branches/20071026_1010/audio)	(révision 180)
@@ -0,0 +1,91 @@
+/*
+ *
+ *  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 <audioclient.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;
+}
+
Index: audioclient.h
===================================================================
--- audioclient.h	(.../tags/20071026_1010/audio)	(révision 0)
+++ audioclient.h	(.../branches/20071026_1010/audio)	(révision 180)
@@ -0,0 +1,304 @@
+/*
+ *
+ *  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
+ *
+ */
+
+/*
+  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-->
+
+  BT_STREAMFD_IND -->
+
+                          <  streams data >
+                             ..........
+
+               on snd_pcm_drop/snd_pcm_drain
+
+                <--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
+
+#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"
+
+/* 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));
+
+/* 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_MONO_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 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;
+	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));
+
+/* 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));
+
+/* BT_STREAMSTART_RSP */
+struct bt_streamstart_rsp {
+	bt_audio_msg_header_t 	h;
+	uint8_t 		posix_errno;
+} __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 */
Index: ctl_bluetooth.c
===================================================================
--- ctl_bluetooth.c	(.../tags/20071026_1010/audio)	(révision 180)
+++ ctl_bluetooth.c	(.../branches/20071026_1010/audio)	(révision 180)
@@ -30,13 +30,13 @@
 
 #include <alsa/asoundlib.h>
 #include <alsa/control_external.h>
 
 #include <bluetooth/bluetooth.h>
 
-#include "ipc.h"
+#include "audioclient.h"
 
 #ifdef ENABLE_DEBUG
 #define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
 #else
 #define DBG(fmt, arg...)
 #endif
@@ -62,13 +62,13 @@
 static void bluetooth_exit(struct bluetooth_data *data)
 {
 	if (data == NULL)
 		return;
 
 	if (data->sock >= 0)
-		close(data->sock);
+		bt_audio_service_close(data->sock);
 
 	free(data);
 }
 
 static void bluetooth_close(snd_ctl_ext_t *ext)
 {
@@ -138,140 +138,135 @@
 	*imax  = BLUETOOTH_MAXVOL;
 
 	return 0;
 }
 
 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;
 }
 
 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;
 }
 
 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);
 
 	if ((ret = bluetooth_read_integer(ext, key, &current)) < 0)
 		return ret;
 
 	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;
 }
 
 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;
 
 	return 1;
 }
@@ -287,40 +282,25 @@
 	.write_integer		= bluetooth_write_integer,
 	.read_event		= bluetooth_read_event,
 };
 
 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;
 
 	memset(data, 0, sizeof(struct bluetooth_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;
 }
 
 SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth)
Index: Makefile.am
===================================================================
--- Makefile.am	(.../tags/20071026_1010/audio)	(révision 180)
+++ Makefile.am	(.../branches/20071026_1010/audio)	(révision 180)
@@ -1,12 +1,12 @@
 
 if AUDIOSERVICE
 if CONFIGFILES
 confdir = $(sysconfdir)/bluetooth
 
-conf_DATA = audio.service
+conf_DATA = audio.service audio.conf
 endif
 
 servicedir = $(libdir)/bluetooth
 
 service_PROGRAMS = bluetoothd-service-audio
 
@@ -20,18 +20,18 @@
 
 if ALSA
 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 audioclient.h audioclient.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 audioclient.h audioclient.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@
 endif
 
 if GSTREAMER
@@ -55,6 +55,15 @@
 
 INCLUDES = -I$(top_srcdir)/common
 
 EXTRA_DIST = audio.service audio.conf audio-api.txt test-audio asound.conf
 
 MAINTAINERCLEANFILES = Makefile.in
+
+#Audio client library support
+audioclientdir = $(libdir)
+audioclient_LTLIBRARIES = libbtaudioclient.la
+audioclient_includedir = $(includedir)/bluetooth
+audioclient_include_HEADERS = rtp.h audioclient.h
+libbtaudioclient_la_SOURCES = rtp.h audioclient.h audioclient.c
+libbtaudioclient_la_LDFLAGS = -module -avoid-version
+

[-- Attachment #3: fchevalier.vcf --]
[-- Type: text/x-vcard, Size: 253 bytes --]

begin:vcard
fn:Fabien CHEVALIER
n:CHEVALIER;Fabien
org:SILICOM
adr:;;4 rue de Jouanet; RENNES ATALANTE;;35700;FRANCE
email;internet:fchevalier@silicom.fr
title:Software & Studies Engineer
tel;work:+33 (0) 2 99 84 17 17
version:2.1
end:vcard


[-- Attachment #4: Type: text/plain, Size: 314 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

[-- Attachment #5: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

             reply	other threads:[~2007-10-31 12:11 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-31 12:11 Fabien Chevalier [this message]
2007-11-01 21:24 ` [Bluez-devel] [PATCH] Audio service Newapi patchv3 thiagoss

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=472870DB.9040204@silicom.fr \
    --to=fchevalier@silicom.fr \
    --cc=bluez-devel@lists.sourceforge.net \
    --cc=bmidgley@xmission.com \
    --cc=johan.hedberg@nokia.com \
    --cc=luiz.dentz@gmail.com \
    --cc=thiagossantos@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.