[PATCH BlueZ 2/5 v2] audio: Remove ALSA support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

ALSA support depend on unix support that is now removed.
---
 Makefile.am           |   29 -
 acinclude.m4          |   16 +-
 audio/bluetooth.conf  |   36 -
 audio/ctl_bluetooth.c |  383 -----------
 audio/pcm_bluetooth.c | 1785 -------------------------------------------------
 configure.ac          |    1 -
 6 files changed, 1 insertion(+), 2249 deletions(-)
 delete mode 100644 audio/bluetooth.conf
 delete mode 100644 audio/ctl_bluetooth.c
 delete mode 100644 audio/pcm_bluetooth.c

diff --git a/Makefile.am b/Makefile.am
index aaae42e..51156fb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -335,35 +335,6 @@ EXTRA_DIST += src/genbuiltin src/bluetooth.conf src/org.bluez.service \
 			audio/telephony-maemo6.c sap/sap-dummy.c sap/sap-u8500.c \
 			proximity/proximity.conf
 
-if ALSA
-alsadir = $(libdir)/alsa-lib
-
-alsa_LTLIBRARIES = audio/libasound_module_pcm_bluetooth.la \
-				audio/libasound_module_ctl_bluetooth.la
-
-audio_libasound_module_pcm_bluetooth_la_SOURCES = audio/pcm_bluetooth.c \
-					audio/rtp.h audio/ipc.h audio/ipc.c
-audio_libasound_module_pcm_bluetooth_la_LDFLAGS = $(AM_LDFLAGS) -module \
-						  -avoid-version
-audio_libasound_module_pcm_bluetooth_la_LIBADD = sbc/libsbc.la \
-					lib/libbluetooth-private.la @ALSA_LIBS@
-audio_libasound_module_pcm_bluetooth_la_CFLAGS = $(AM_CFLAGS) @ALSA_CFLAGS@
-
-audio_libasound_module_ctl_bluetooth_la_SOURCES = audio/ctl_bluetooth.c \
-					audio/rtp.h audio/ipc.h audio/ipc.c
-audio_libasound_module_ctl_bluetooth_la_LDFLAGS = $(AM_LDFLAGS) -module \
-						  -avoid-version
-audio_libasound_module_ctl_bluetooth_la_LIBADD = \
-					lib/libbluetooth-private.la @ALSA_LIBS@
-audio_libasound_module_ctl_bluetooth_la_CFLAGS = $(AM_CFLAGS) @ALSA_CFLAGS@
-
-if DATAFILES
-alsaconfdir = $(datadir)/alsa
-
-alsaconf_DATA = audio/bluetooth.conf
-endif
-endif
-
 if AUDIOPLUGIN
 if GSTREAMER
 gstreamerdir = $(libdir)/gstreamer-0.10
diff --git a/acinclude.m4 b/acinclude.m4
index 1d6d736..ab0ebba 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -114,13 +114,6 @@ AC_DEFUN([AC_PATH_GSTREAMER], [
 	AC_SUBST(GSTREAMER_PLUGINSDIR)
 ])
 
-AC_DEFUN([AC_PATH_ALSA], [
-	PKG_CHECK_MODULES(ALSA, alsa, alsa_found=yes, alsa_found=no)
-	AC_CHECK_LIB(rt, clock_gettime, ALSA_LIBS="$ALSA_LIBS -lrt", alsa_found=no)
-	AC_SUBST(ALSA_CFLAGS)
-	AC_SUBST(ALSA_LIBS)
-])
-
 AC_DEFUN([AC_PATH_USB], [
 	PKG_CHECK_MODULES(USB, libusb, usb_found=yes, usb_found=no)
 	AC_SUBST(USB_CFLAGS)
@@ -176,7 +169,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	sndfile_enable=${sndfile_found}
 	hal_enable=no
 	usb_enable=${usb_found}
-	alsa_enable=${alsa_found}
 	gstreamer_enable=${gstreamer_found}
 	audio_enable=yes
 	input_enable=yes
@@ -257,10 +249,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		gstreamer_enable=${enableval}
 	])
 
-	AC_ARG_ENABLE(alsa, AC_HELP_STRING([--enable-alsa], [enable ALSA support]), [
-		alsa_enable=${enableval}
-	])
-
 	AC_ARG_ENABLE(usb, AC_HELP_STRING([--enable-usb], [enable USB support]), [
 		usb_enable=${enableval}
 	])
@@ -368,9 +356,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 
 	AM_CONDITIONAL(SNDFILE, test "${sndfile_enable}" = "yes" && test "${sndfile_found}" = "yes")
 	AM_CONDITIONAL(USB, test "${usb_enable}" = "yes" && test "${usb_found}" = "yes")
-	AM_CONDITIONAL(SBC, test "${alsa_enable}" = "yes" || test "${gstreamer_enable}" = "yes" ||
-									test "${test_enable}" = "yes")
-	AM_CONDITIONAL(ALSA, test "${alsa_enable}" = "yes" && test "${alsa_found}" = "yes")
+	AM_CONDITIONAL(SBC, test "${gstreamer_enable}" = "yes" || test "${test_enable}" = "yes")
 	AM_CONDITIONAL(GSTREAMER, test "${gstreamer_enable}" = "yes" && test "${gstreamer_found}" = "yes")
 	AM_CONDITIONAL(AUDIOPLUGIN, test "${audio_enable}" = "yes")
 	AM_CONDITIONAL(INPUTPLUGIN, test "${input_enable}" = "yes")
diff --git a/audio/bluetooth.conf b/audio/bluetooth.conf
deleted file mode 100644
index 55b51e4..0000000
--- a/audio/bluetooth.conf
+++ /dev/null
@@ -1,36 +0,0 @@
-# Please note that this ALSA configuration file fragment needs be enabled in
-# /etc/asound.conf or a similar configuration file with directives similar to
-# the following:
-#
-#@hooks [
-#	{
-#		func load
-#		files [
-#			"/etc/alsa/bluetooth.conf"
-#		]
-#		errors false
-#	}
-#]
-
-pcm.rawbluetooth {
-	@args [ ADDRESS ]
-	@args.ADDRESS {
-		type string
-	}
-	type bluetooth
-	device $ADDRESS
-}
-
-pcm.bluetooth {
-	@args [ ADDRESS ]
-	@args.ADDRESS {
-		type string
-	}
-	type plug
-	slave {
-		pcm {
-			type bluetooth
-			device $ADDRESS
-		}
-	}
-}
diff --git a/audio/ctl_bluetooth.c b/audio/ctl_bluetooth.c
deleted file mode 100644
index a16f476..0000000
--- a/audio/ctl_bluetooth.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@xxxxxxxxxxxx>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <alsa/asoundlib.h>
-#include <alsa/control_external.h>
-
-#include <bluetooth/bluetooth.h>
-
-#include "ipc.h"
-
-#ifdef ENABLE_DEBUG
-#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-#define BLUETOOTH_MINVOL 0
-#define BLUETOOTH_MAXVOL 15
-
-struct bluetooth_data {
-	snd_ctl_ext_t ext;
-	int sock;
-};
-
-enum {
-	BLUETOOTH_PLAYBACK,
-	BLUETOOTH_CAPTURE,
-};
-
-static const char *vol_devices[2] = {
-	[BLUETOOTH_PLAYBACK]	= "Playback volume",
-	[BLUETOOTH_CAPTURE]	= "Capture volume",
-};
-
-static void bluetooth_exit(struct bluetooth_data *data)
-{
-	if (data == NULL)
-		return;
-
-	if (data->sock >= 0)
-		bt_audio_service_close(data->sock);
-
-	free(data);
-}
-
-static void bluetooth_close(snd_ctl_ext_t *ext)
-{
-	struct bluetooth_data *data = ext->private_data;
-
-	DBG("ext %p", ext);
-
-	bluetooth_exit(data);
-}
-
-static int bluetooth_elem_count(snd_ctl_ext_t *ext)
-{
-	DBG("ext %p", ext);
-
-	return 2;
-}
-
-static int bluetooth_elem_list(snd_ctl_ext_t *ext,
-				unsigned int offset, snd_ctl_elem_id_t *id)
-{
-	DBG("ext %p offset %d id %p", ext, offset, id);
-
-	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
-
-	if (offset > 1)
-		return -EINVAL;
-
-	snd_ctl_elem_id_set_name(id, vol_devices[offset]);
-
-	return 0;
-}
-
-static snd_ctl_ext_key_t bluetooth_find_elem(snd_ctl_ext_t *ext,
-						const snd_ctl_elem_id_t *id)
-{
-	const char *name = snd_ctl_elem_id_get_name(id);
-	int i;
-
-	DBG("ext %p id %p name '%s'", ext, id, name);
-
-	for (i = 0; i < 2; i++)
-		if (strcmp(name, vol_devices[i]) == 0)
-			return i;
-
-	return SND_CTL_EXT_KEY_NOT_FOUND;
-}
-
-static int bluetooth_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
-			int *type, unsigned int *acc, unsigned int *count)
-{
-	DBG("ext %p key %ld", ext, key);
-
-	*type = SND_CTL_ELEM_TYPE_INTEGER;
-	*acc = SND_CTL_EXT_ACCESS_READWRITE;
-	*count = 1;
-
-	return 0;
-}
-
-static int bluetooth_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
-					long *imin, long *imax, long *istep)
-{
-	DBG("ext %p key %ld", ext, key);
-
-	*istep = 1;
-	*imin  = BLUETOOTH_MINVOL;
-	*imax  = BLUETOOTH_MAXVOL;
-
-	return 0;
-}
-
-static int bluetooth_send_ctl(struct bluetooth_data *data,
-			uint8_t mode, uint8_t key, struct bt_control_rsp *rsp)
-{
-	int ret;
-	struct bt_control_req *req = (void *) rsp;
-	bt_audio_error_t *err = (void *) rsp;
-	const char *type, *name;
-
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	req->h.type = BT_REQUEST;
-	req->h.name = BT_CONTROL;
-	req->h.length = sizeof(*req);
-
-	req->mode = mode;
-	req->key = key;
-
-	ret = send(data->sock, req, BT_SUGGESTED_BUFFER_SIZE, MSG_NOSIGNAL);
-	if (ret <= 0) {
-		SYSERR("Unable to request new volume value to server");
-		return  -errno;
-	}
-
-	ret = recv(data->sock, rsp, BT_SUGGESTED_BUFFER_SIZE, 0);
-	if (ret <= 0) {
-		SNDERR("Unable to receive new volume value from server");
-		return  -errno;
-	}
-
-	if (rsp->h.type == BT_ERROR) {
-		SNDERR("BT_CONTROL failed : %s (%d)",
-					strerror(err->posix_errno),
-					err->posix_errno);
-		return -err->posix_errno;
-	}
-
-	type = bt_audio_strtype(rsp->h.type);
-	if (!type) {
-		SNDERR("Bogus message type %d "
-				"received from audio service",
-				rsp->h.type);
-		return -EINVAL;
-	}
-
-	name = bt_audio_strname(rsp->h.name);
-	if (!name) {
-		SNDERR("Bogus message name %d "
-				"received from audio service",
-				rsp->h.name);
-		return -EINVAL;
-	}
-
-	if (rsp->h.name != BT_CONTROL) {
-		SNDERR("Unexpected message %s received", type);
-		return -EINVAL;
-	}
-
-	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;
-	int ret;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_control_rsp *rsp = (void *) buf;
-
-	DBG("ext %p key %ld", ext, key);
-
-	memset(buf, 0, sizeof(buf));
-	*value = 0;
-
-	ret = bluetooth_send_ctl(data, key, 0, rsp);
-	if (ret == 0)
-		*value = rsp->key;
-
-	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;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_control_rsp *rsp = (void *) buf;
-	long current;
-	int ret, keyvalue;
-
-	DBG("ext %p key %ld", ext, key);
-
-	ret = bluetooth_read_integer(ext, key, &current);
-	if (ret < 0)
-		return ret;
-
-	if (*value == current)
-		return 0;
-
-	while (*value != current) {
-		keyvalue = (*value > current) ? BT_CONTROL_KEY_VOL_UP :
-				BT_CONTROL_KEY_VOL_DOWN;
-
-		ret = bluetooth_send_ctl(data, key, keyvalue, rsp);
-		if (ret < 0)
-			break;
-
-		current = keyvalue;
-	}
-
-	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;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_control_ind *ind = (void *) buf;
-	int err;
-	const char *type, *name;
-
-	DBG("ext %p id %p", ext, id);
-
-	memset(buf, 0, sizeof(buf));
-
-	err = recv(data->sock, ind, BT_SUGGESTED_BUFFER_SIZE, MSG_DONTWAIT);
-	if (err < 0) {
-		err = -errno;
-		SNDERR("Failed while receiving data: %s (%d)", strerror(-err),
-									-err);
-		return err;
-	}
-
-	type = bt_audio_strtype(ind->h.type);
-	if (!type) {
-		SNDERR("Bogus message type %d "
-				"received from audio service",
-				ind->h.type);
-		return -EAGAIN;
-	}
-
-	name = bt_audio_strname(ind->h.name);
-	if (!name) {
-		SNDERR("Bogus message name %d "
-				"received from audio service",
-				ind->h.name);
-		return -EAGAIN;
-	}
-
-	if (ind->h.name != BT_CONTROL) {
-		SNDERR("Unexpected message %s received", name);
-		return -EAGAIN;
-	}
-
-	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
-	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;
-}
-
-static snd_ctl_ext_callback_t bluetooth_callback = {
-	.close			= bluetooth_close,
-	.elem_count		= bluetooth_elem_count,
-	.elem_list		= bluetooth_elem_list,
-	.find_elem		= bluetooth_find_elem,
-	.get_attribute		= bluetooth_get_attribute,
-	.get_integer_info	= bluetooth_get_integer_info,
-	.read_integer		= bluetooth_read_integer,
-	.write_integer		= bluetooth_write_integer,
-	.read_event		= bluetooth_read_event,
-};
-
-static int bluetooth_init(struct bluetooth_data *data)
-{
-	int sk;
-
-	if (!data)
-		return -EINVAL;
-
-	memset(data, 0, sizeof(struct bluetooth_data));
-
-	data->sock = -1;
-
-	sk = bt_audio_service_open();
-	if (sk < 0)
-		return -errno;
-
-	data->sock = sk;
-
-	return 0;
-}
-
-SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth);
-
-SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth)
-{
-	struct bluetooth_data *data;
-	int err;
-
-	DBG("Bluetooth Control plugin");
-
-	data = malloc(sizeof(struct bluetooth_data));
-	if (!data) {
-		err = -ENOMEM;
-		goto error;
-	}
-
-	err = bluetooth_init(data);
-	if (err < 0)
-		goto error;
-
-	data->ext.version = SND_CTL_EXT_VERSION;
-	data->ext.card_idx = -1;
-
-	strncpy(data->ext.id, "bluetooth", sizeof(data->ext.id) - 1);
-	strncpy(data->ext.driver, "Bluetooth-Audio", sizeof(data->ext.driver) - 1);
-	strncpy(data->ext.name, "Bluetooth Audio", sizeof(data->ext.name) - 1);
-	strncpy(data->ext.longname, "Bluetooth Audio", sizeof(data->ext.longname) - 1);
-	strncpy(data->ext.mixername, "Bluetooth Audio", sizeof(data->ext.mixername) - 1);
-
-	data->ext.callback = &bluetooth_callback;
-	data->ext.poll_fd = data->sock;
-	data->ext.private_data = data;
-
-	err = snd_ctl_ext_create(&data->ext, name, mode);
-	if (err < 0)
-		goto error;
-
-	*handlep = data->ext.handle;
-
-	return 0;
-
-error:
-	bluetooth_exit(data);
-
-	return err;
-}
-
-SND_CTL_PLUGIN_SYMBOL(bluetooth);
diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c
deleted file mode 100644
index b9da805..0000000
--- a/audio/pcm_bluetooth.c
+++ /dev/null
@@ -1,1785 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2006-2010  Nokia Corporation
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@xxxxxxxxxxxx>
- *
- *
- *  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
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <time.h>
-#include <sys/time.h>
-#include <pthread.h>
-#include <signal.h>
-#include <limits.h>
-
-#include <netinet/in.h>
-
-#include <alsa/asoundlib.h>
-#include <alsa/pcm_external.h>
-
-#include "ipc.h"
-#include "sbc.h"
-#include "rtp.h"
-
-/* #define ENABLE_DEBUG */
-
-#define UINT_SECS_MAX (UINT_MAX / 1000000 - 1)
-
-#define MIN_PERIOD_TIME 1
-
-#define BUFFER_SIZE 2048
-
-#ifdef ENABLE_DEBUG
-#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-#ifndef SOL_SCO
-#define SOL_SCO 17
-#endif
-
-#ifndef SCO_TXBUFS
-#define SCO_TXBUFS 0x03
-#endif
-
-#ifndef SCO_RXBUFS
-#define SCO_RXBUFS 0x04
-#endif
-
-#ifndef MIN
-# define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
-#ifndef MAX
-# define MAX(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
-#define MAX_BITPOOL 64
-#define MIN_BITPOOL 2
-
-/* adapted from glibc sys/time.h timersub() macro */
-#define priv_timespecsub(a, b, result)					\
-	do {								\
-		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;		\
-		(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;	\
-		if ((result)->tv_nsec < 0) {				\
-			--(result)->tv_sec;				\
-			(result)->tv_nsec += 1000000000;		\
-		}							\
-	} while (0)
-
-struct bluetooth_a2dp {
-	sbc_capabilities_t sbc_capabilities;
-	sbc_t sbc;				/* Codec data */
-	int sbc_initialized;			/* Keep track if the encoder is initialized */
-	unsigned int codesize;			/* SBC codesize */
-	int samples;				/* Number of encoded samples */
-	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
-	unsigned 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;
-	int autoconnect;
-};
-
-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;
-	int transport;					/* chosen transport SCO or AD2P */
-	unsigned 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 */
-	unsigned 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);
-
-	return 0;
-}
-
-static int bluetooth_stop(snd_pcm_ioplug_t *io)
-{
-	DBG("bluetooth_stop %p", io);
-
-	return 0;
-}
-
-static void *playback_hw_thread(void *param)
-{
-	struct bluetooth_data *data = param;
-	unsigned int prev_periods;
-	double period_time;
-	struct timespec start;
-	struct pollfd fds[2];
-	int poll_timeout;
-
-	data->server.events = POLLIN;
-	/* note: only errors for data->stream.events */
-
-	fds[0] = data->server;
-	fds[1] = data->stream;
-
-	prev_periods = 0;
-	period_time = 1000000.0 * data->io.period_size / data->io.rate;
-	if (period_time > (int) (MIN_PERIOD_TIME * 1000))
-		poll_timeout = (int) (period_time / 1000.0f);
-	else
-		poll_timeout = MIN_PERIOD_TIME;
-
-	clock_gettime(CLOCK_MONOTONIC, &start);
-
-	while (1) {
-		unsigned int dtime, periods;
-		struct timespec cur, delta;
-		int ret;
-
-		if (data->stopped)
-			goto iter_sleep;
-
-		if (data->reset) {
-			DBG("Handle XRUN in hw-thread.");
-			data->reset = 0;
-			clock_gettime(CLOCK_MONOTONIC, &start);
-			prev_periods = 0;
-		}
-
-		clock_gettime(CLOCK_MONOTONIC, &cur);
-
-		priv_timespecsub(&cur, &start, &delta);
-
-		dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000;
-		periods = 1.0 * dtime / period_time;
-
-		if (periods > prev_periods) {
-			char c = 'w';
-			int frags = periods - prev_periods, n;
-
-			data->hw_ptr += frags * data->io.period_size;
-			data->hw_ptr %= data->io.buffer_size;
-
-			for (n = 0; n < frags; n++) {
-				/* Notify user that hardware pointer
-				 * has moved * */
-				if (write(data->pipefd[1], &c, 1) < 0)
-					pthread_testcancel();
-			}
-
-			/* Reset point of reference to avoid too big values
-			 * that wont fit an unsigned int */
-			if ((unsigned int) delta.tv_sec < UINT_SECS_MAX)
-				prev_periods = periods;
-			else {
-				prev_periods = 0;
-				clock_gettime(CLOCK_MONOTONIC, &start);
-			}
-		}
-
-iter_sleep:
-		/* sleep up to one period interval */
-		ret = poll(fds, 2, poll_timeout);
-
-		if (ret < 0) {
-			if (errno != EINTR) {
-				SNDERR("poll error: %s (%d)", strerror(errno),
-								errno);
-				break;
-			}
-		} else if (ret > 0) {
-			ret = (fds[0].revents) ? 0 : 1;
-			SNDERR("poll fd %d revents %d", ret, fds[ret].revents);
-			if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL))
-				break;
-		}
-
-		/* Offer opportunity to be canceled by main thread */
-		pthread_testcancel();
-	}
-
-	data->hw_thread = 0;
-	pthread_exit(NULL);
-}
-
-static int bluetooth_playback_start(snd_pcm_ioplug_t *io)
-{
-	struct bluetooth_data *data = io->private_data;
-	int err;
-
-	DBG("%p", io);
-
-	data->stopped = 0;
-
-	if (data->hw_thread)
-		return 0;
-
-	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
-
-	return -err;
-}
-
-static int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
-{
-	struct bluetooth_data *data = io->private_data;
-
-	DBG("%p", io);
-
-	data->stopped = 1;
-
-	return 0;
-}
-
-static snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
-{
-	struct bluetooth_data *data = io->private_data;
-
-	return data->hw_ptr;
-}
-
-static void bluetooth_exit(struct bluetooth_data *data)
-{
-	struct bluetooth_a2dp *a2dp = &data->a2dp;
-
-	if (data->server.fd >= 0)
-		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 (a2dp->sbc_initialized)
-		sbc_finish(&a2dp->sbc);
-
-	if (data->pipefd[0] > 0)
-		close(data->pipefd[0]);
-
-	if (data->pipefd[1] > 0)
-		close(data->pipefd[1]);
-
-	free(data);
-}
-
-static int bluetooth_close(snd_pcm_ioplug_t *io)
-{
-	struct bluetooth_data *data = io->private_data;
-
-	DBG("%p", io);
-
-	bluetooth_exit(data);
-
-	return 0;
-}
-
-static int bluetooth_prepare(snd_pcm_ioplug_t *io)
-{
-	struct bluetooth_data *data = io->private_data;
-	char c = 'w';
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_start_stream_req *req = (void *) buf;
-	struct bt_start_stream_rsp *rsp = (void *) buf;
-	struct bt_new_stream_ind *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 */
-		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;
-
-	/* send start */
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	req->h.type = BT_REQUEST;
-	req->h.name = BT_START_STREAM;
-	req->h.length = sizeof(*req);
-
-	err = audioservice_send(data->server.fd, &req->h);
-	if (err < 0)
-		return err;
-
-	rsp->h.length = sizeof(*rsp);
-	err = audioservice_expect(data->server.fd, &rsp->h,
-					BT_START_STREAM);
-	if (err < 0)
-		return err;
-
-	ind->h.length = sizeof(*ind);
-	err = audioservice_expect(data->server.fd, &ind->h,
-					BT_NEW_STREAM);
-	if (err < 0)
-		return err;
-
-	if (data->stream.fd >= 0)
-		close(data->stream.fd);
-
-	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;
-
-		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,
-						sizeof(period_count)) == 0)
-			return 0;
-
-		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
-						SO_SNDBUF : SO_RCVBUF;
-
-		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
-						sizeof(period_count)) == 0)
-			return 0;
-
-		/* FIXME : handle error codes */
-	}
-
-	/* wake up any client polling at us */
-	if (write(data->pipefd[1], &c, 1) < 0) {
-		err = -errno;
-		return err;
-	}
-
-	return 0;
-}
-
-static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
-					snd_pcm_hw_params_t *params)
-{
-	struct bluetooth_data *data = io->private_data;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_open_req *open_req = (void *) buf;
-	struct bt_open_rsp *open_rsp = (void *) buf;
-	struct bt_set_configuration_req *req = (void *) buf;
-	struct bt_set_configuration_rsp *rsp = (void *) buf;
-	int err;
-
-	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
-					io->period_size, io->buffer_size);
-
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	open_req->h.type = BT_REQUEST;
-	open_req->h.name = BT_OPEN;
-	open_req->h.length = sizeof(*open_req);
-
-	strncpy(open_req->destination, data->alsa_config.device, 18);
-	open_req->seid = BT_A2DP_SEID_RANGE + 1;
-	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
-			BT_WRITE_LOCK : BT_READ_LOCK);
-
-	err = audioservice_send(data->server.fd, &open_req->h);
-	if (err < 0)
-		return err;
-
-	open_rsp->h.length = sizeof(*open_rsp);
-	err = audioservice_expect(data->server.fd, &open_rsp->h,
-					BT_OPEN);
-	if (err < 0)
-		return err;
-
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	req->h.type = BT_REQUEST;
-	req->h.name = BT_SET_CONFIGURATION;
-	req->h.length = sizeof(*req);
-
-	req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
-	req->codec.seid = BT_A2DP_SEID_RANGE + 1;
-	req->codec.length = sizeof(pcm_capabilities_t);
-
-	req->h.length += req->codec.length - sizeof(req->codec);
-	err = audioservice_send(data->server.fd, &req->h);
-	if (err < 0)
-		return err;
-
-	rsp->h.length = sizeof(*rsp);
-	err = audioservice_expect(data->server.fd, &rsp->h,
-					BT_SET_CONFIGURATION);
-	if (err < 0)
-		return err;
-
-	data->transport = BT_CAPABILITIES_TRANSPORT_SCO;
-	data->link_mtu = rsp->link_mtu;
-
-	return 0;
-}
-
-static uint8_t default_bitpool(uint8_t freq, uint8_t mode)
-{
-	switch (freq) {
-	case BT_SBC_SAMPLING_FREQ_16000:
-	case BT_SBC_SAMPLING_FREQ_32000:
-		return 53;
-	case BT_SBC_SAMPLING_FREQ_44100:
-		switch (mode) {
-		case BT_A2DP_CHANNEL_MODE_MONO:
-		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
-			return 31;
-		case BT_A2DP_CHANNEL_MODE_STEREO:
-		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
-			return 53;
-		default:
-			DBG("Invalid channel mode %u", mode);
-			return 53;
-		}
-	case BT_SBC_SAMPLING_FREQ_48000:
-		switch (mode) {
-		case BT_A2DP_CHANNEL_MODE_MONO:
-		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
-			return 29;
-		case BT_A2DP_CHANNEL_MODE_STEREO:
-		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
-			return 51;
-		default:
-			DBG("Invalid channel mode %u", mode);
-			return 51;
-		}
-	default:
-		DBG("Invalid sampling freq %u", freq);
-		return 53;
-	}
-}
-
-static int bluetooth_a2dp_init(struct bluetooth_data *data,
-					snd_pcm_hw_params_t *params)
-{
-	struct bluetooth_alsa_config *cfg = &data->alsa_config;
-	sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities;
-	unsigned int max_bitpool, min_bitpool, rate, channels;
-	int dir;
-
-	snd_pcm_hw_params_get_rate(params, &rate, &dir);
-	snd_pcm_hw_params_get_channels(params, &channels);
-
-	switch (rate) {
-	case 48000:
-		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
-		break;
-	case 44100:
-		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
-		break;
-	case 32000:
-		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
-		break;
-	case 16000:
-		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
-		break;
-	default:
-		DBG("Rate %d not supported", rate);
-		return -1;
-	}
-
-	if (cfg->has_channel_mode)
-		cap->channel_mode = cfg->channel_mode;
-	else if (channels == 2) {
-		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
-			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
-		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
-			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
-		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
-			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
-	} else {
-		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
-			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
-	}
-
-	if (!cap->channel_mode) {
-		DBG("No supported channel modes");
-		return -1;
-	}
-
-	if (cfg->has_block_length)
-		cap->block_length = cfg->block_length;
-	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
-		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
-	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
-		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
-	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
-		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
-	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
-		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
-	else {
-		DBG("No supported block lengths");
-		return -1;
-	}
-
-	if (cfg->has_subbands)
-		cap->subbands = cfg->subbands;
-	if (cap->subbands & BT_A2DP_SUBBANDS_8)
-		cap->subbands = BT_A2DP_SUBBANDS_8;
-	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
-		cap->subbands = BT_A2DP_SUBBANDS_4;
-	else {
-		DBG("No supported subbands");
-		return -1;
-	}
-
-	if (cfg->has_allocation_method)
-		cap->allocation_method = cfg->allocation_method;
-	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
-		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
-	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
-		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
-
-	if (cfg->has_bitpool)
-		min_bitpool = max_bitpool = cfg->bitpool;
-	else {
-		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
-		max_bitpool = MIN(default_bitpool(cap->frequency,
-					cap->channel_mode),
-					cap->max_bitpool);
-	}
-
-	cap->min_bitpool = min_bitpool;
-	cap->max_bitpool = max_bitpool;
-
-	return 0;
-}
-
-static void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp)
-{
-	sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
-
-	if (a2dp->sbc_initialized)
-		sbc_reinit(&a2dp->sbc, 0);
-	else
-		sbc_init(&a2dp->sbc, 0);
-	a2dp->sbc_initialized = 1;
-
-	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
-		a2dp->sbc.frequency = SBC_FREQ_16000;
-
-	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
-		a2dp->sbc.frequency = SBC_FREQ_32000;
-
-	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
-		a2dp->sbc.frequency = SBC_FREQ_44100;
-
-	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
-		a2dp->sbc.frequency = SBC_FREQ_48000;
-
-	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
-		a2dp->sbc.mode = SBC_MODE_MONO;
-
-	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
-		a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
-
-	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
-		a2dp->sbc.mode = SBC_MODE_STEREO;
-
-	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
-		a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
-
-	a2dp->sbc.allocation = active_capabilities.allocation_method
-				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
-				: SBC_AM_LOUDNESS;
-
-	switch (active_capabilities.subbands) {
-	case BT_A2DP_SUBBANDS_4:
-		a2dp->sbc.subbands = SBC_SB_4;
-		break;
-	case BT_A2DP_SUBBANDS_8:
-		a2dp->sbc.subbands = SBC_SB_8;
-		break;
-	}
-
-	switch (active_capabilities.block_length) {
-	case BT_A2DP_BLOCK_LENGTH_4:
-		a2dp->sbc.blocks = SBC_BLK_4;
-		break;
-	case BT_A2DP_BLOCK_LENGTH_8:
-		a2dp->sbc.blocks = SBC_BLK_8;
-		break;
-	case BT_A2DP_BLOCK_LENGTH_12:
-		a2dp->sbc.blocks = SBC_BLK_12;
-		break;
-	case BT_A2DP_BLOCK_LENGTH_16:
-		a2dp->sbc.blocks = SBC_BLK_16;
-		break;
-	}
-
-	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
-	a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
-	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
-}
-
-static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
-					snd_pcm_hw_params_t *params)
-{
-	struct bluetooth_data *data = io->private_data;
-	struct bluetooth_a2dp *a2dp = &data->a2dp;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_open_req *open_req = (void *) buf;
-	struct bt_open_rsp *open_rsp = (void *) buf;
-	struct bt_set_configuration_req *req = (void *) buf;
-	struct bt_set_configuration_rsp *rsp = (void *) buf;
-	int err;
-
-	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
-					io->period_size, io->buffer_size);
-
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	open_req->h.type = BT_REQUEST;
-	open_req->h.name = BT_OPEN;
-	open_req->h.length = sizeof(*open_req);
-
-	strncpy(open_req->destination, data->alsa_config.device, 18);
-	open_req->seid = a2dp->sbc_capabilities.capability.seid;
-	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
-			BT_WRITE_LOCK : BT_READ_LOCK);
-
-	err = audioservice_send(data->server.fd, &open_req->h);
-	if (err < 0)
-		return err;
-
-	open_rsp->h.length = sizeof(*open_rsp);
-	err = audioservice_expect(data->server.fd, &open_rsp->h,
-					BT_OPEN);
-	if (err < 0)
-		return err;
-
-	err = bluetooth_a2dp_init(data, params);
-	if (err < 0)
-		return err;
-
-	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	req->h.type = BT_REQUEST;
-	req->h.name = BT_SET_CONFIGURATION;
-	req->h.length = sizeof(*req);
-
-	memcpy(&req->codec, &a2dp->sbc_capabilities,
-			sizeof(a2dp->sbc_capabilities));
-
-	req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
-	req->codec.length = sizeof(a2dp->sbc_capabilities);
-	req->h.length += req->codec.length - sizeof(req->codec);
-
-	err = audioservice_send(data->server.fd, &req->h);
-	if (err < 0)
-		return err;
-
-	rsp->h.length = sizeof(*rsp);
-	err = audioservice_expect(data->server.fd, &rsp->h,
-					BT_SET_CONFIGURATION);
-	if (err < 0)
-		return err;
-
-	data->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
-	data->link_mtu = rsp->link_mtu;
-
-	/* Setup SBC encoder now we agree on parameters */
-	bluetooth_a2dp_setup(a2dp);
-
-	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;
-
-	assert(io);
-
-	if (space < 1)
-		return 0;
-
-	pfd[0].fd = data->stream.fd;
-	pfd[0].events = POLLIN;
-	pfd[0].revents = 0;
-
-	return 1;
-}
-
-static int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
-					struct pollfd *pfds, unsigned int nfds,
-					unsigned short *revents)
-{
-	assert(pfds && nfds == 1 && revents);
-
-	*revents = pfds[0].revents;
-
-	return 0;
-}
-
-static int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io)
-{
-	return 2;
-}
-
-static int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
-					struct pollfd *pfd, unsigned int space)
-{
-	struct bluetooth_data *data = io->private_data;
-
-	DBG("");
-
-	assert(data->pipefd[0] >= 0);
-
-	if (space < 2)
-		return 0;
-
-	pfd[0].fd = data->pipefd[0];
-	pfd[0].events = POLLIN;
-	pfd[0].revents = 0;
-	pfd[1].fd = data->stream.fd;
-	pfd[1].events = POLLERR | POLLHUP | POLLNVAL;
-	pfd[1].revents = 0;
-
-	return 2;
-}
-
-static int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
-					struct pollfd *pfds, unsigned int nfds,
-					unsigned short *revents)
-{
-	static char buf[1];
-
-	DBG("");
-
-	assert(pfds);
-	assert(nfds == 2);
-	assert(revents);
-	assert(pfds[0].fd >= 0);
-	assert(pfds[1].fd >= 0);
-
-	if (io->state != SND_PCM_STATE_PREPARED)
-		if (read(pfds[0].fd, buf, 1) < 0)
-			SYSERR("read error: %s (%d)", strerror(errno), errno);
-
-	if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
-		io->state = SND_PCM_STATE_DISCONNECTED;
-
-	*revents = (pfds[0].revents & POLLIN) ? POLLOUT : 0;
-
-	return 0;
-}
-
-
-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;
-	snd_pcm_uframes_t frames_to_write, ret;
-	unsigned char *buff;
-	unsigned int frame_size = 0;
-	int nrecv;
-
-	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
-			areas->step, areas->first, offset, size, io->nonblock);
-
-	frame_size = areas->step / 8;
-
-	if (data->count > 0)
-		goto proceed;
-
-	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
-					io->nonblock ? MSG_DONTWAIT : 0);
-
-	if (nrecv < 0) {
-		ret = (errno == EPIPE) ? -EIO : -errno;
-		goto done;
-	}
-
-	if ((unsigned int) nrecv != data->link_mtu) {
-		ret = -EIO;
-		SNDERR(strerror(-ret));
-		goto done;
-	}
-
-	/* Increment hardware transmition pointer */
-	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) <= data->link_mtu)
-		frames_to_write = size;
-	else
-		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 %= data->link_mtu;
-
-	/* Return written frames count */
-	ret = frames_to_write;
-
-done:
-	DBG("returning %lu", ret);
-	return ret;
-}
-
-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;
-	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",
-			areas->step, areas->first, offset, size, io->nonblock);
-
-	if (io->hw_ptr > io->appl_ptr) {
-		ret = bluetooth_playback_stop(io);
-		if (ret == 0)
-			ret = -EPIPE;
-		goto done;
-	}
-
-	frame_size = areas->step / 8;
-	if ((data->count + size * frame_size) <= data->link_mtu)
-		frames_to_read = size;
-	else
-		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 != data->link_mtu) {
-		ret = frames_to_read;
-		goto done;
-	}
-
-	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;
-	} else if (rsend < 0)
-		ret = (errno == EPIPE) ? -EIO : -errno;
-	else
-		ret = -EIO;
-
-done:
-	DBG("returning %ld", ret);
-	return ret;
-}
-
-static snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
-				const snd_pcm_channel_area_t *areas,
-				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
-{
-	snd_pcm_uframes_t ret = 0;
-	return ret;
-}
-
-static int avdtp_write(struct bluetooth_data *data)
-{
-	int err;
-	struct rtp_header *header;
-	struct rtp_payload *payload;
-	struct bluetooth_a2dp *a2dp = &data->a2dp;
-
-	header = (void *) a2dp->buffer;
-	payload = (void *) (a2dp->buffer + sizeof(*header));
-
-	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
-
-	payload->frame_count = a2dp->frame_count;
-	header->v = 2;
-	header->pt = 1;
-	header->sequence_number = htons(a2dp->seq_num);
-	header->timestamp = htonl(a2dp->nsamples);
-	header->ssrc = htonl(1);
-
-	err = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
-	if (err < 0) {
-		err = -errno;
-		DBG("send failed: %s (%d)", strerror(-err), -err);
-	}
-
-	/* Reset buffer of data to send */
-	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
-	a2dp->frame_count = 0;
-	a2dp->samples = 0;
-	a2dp->seq_num++;
-
-	return err;
-}
-
-static snd_pcm_sframes_t bluetooth_a2dp_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 bluetooth_a2dp *a2dp = &data->a2dp;
-	snd_pcm_sframes_t ret = 0;
-	unsigned int bytes_left;
-	int frame_size, encoded;
-	ssize_t written;
-	uint8_t *buff;
-
-	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
-				areas->step, areas->first, offset, size);
-	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
-			io->appl_ptr - io->hw_ptr);
-
-	/* Calutate starting pointers */
-	frame_size = areas->step / 8;
-	bytes_left = size * frame_size;
-	buff = (uint8_t *) areas->addr +
-				(areas->first + areas->step * (offset)) / 8;
-
-	/* Check for underrun */
-	if (io->hw_ptr > io->appl_ptr) {
-		ret = bluetooth_playback_stop(io);
-		if (ret == 0)
-			ret = -EPIPE;
-		data->reset = 1;
-		return ret;
-	}
-
-	/* Check if we should autostart */
-	if (io->state == SND_PCM_STATE_PREPARED) {
-		snd_pcm_sw_params_t *swparams;
-		snd_pcm_uframes_t threshold;
-
-		snd_pcm_sw_params_malloc(&swparams);
-		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
-				!snd_pcm_sw_params_get_start_threshold(swparams,
-								&threshold)) {
-			if (io->appl_ptr >= threshold) {
-				ret = snd_pcm_start(io->pcm);
-				if (ret != 0)
-					return ret;
-			}
-		}
-
-		snd_pcm_sw_params_free(swparams);
-	}
-
-	/* Check if we have any left over data from the last write */
-	if (data->count > 0) {
-		unsigned int additional_bytes_needed =
-						a2dp->codesize - data->count;
-		if (additional_bytes_needed > bytes_left)
-			goto out;
-
-		memcpy(data->buffer + data->count, buff,
-						additional_bytes_needed);
-
-		/* Enough data to encode (sbc wants 1k blocks) */
-		encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize,
-					a2dp->buffer + a2dp->count,
-					sizeof(a2dp->buffer) - a2dp->count,
-								&written);
-		if (encoded <= 0) {
-			DBG("Encoding error %d", encoded);
-			goto done;
-		}
-
-		/* Increment a2dp buffers */
-		a2dp->count += written;
-		a2dp->frame_count++;
-		a2dp->samples += encoded / frame_size;
-		a2dp->nsamples += encoded / frame_size;
-
-		/* No space left for another frame then send */
-		if (a2dp->count + written >= data->link_mtu) {
-			avdtp_write(data);
-			DBG("sending packet %d, count %d, link_mtu %u",
-					a2dp->seq_num, a2dp->count,
-							data->link_mtu);
-		}
-
-		/* Increment up buff pointer to take into account
-		 * the data processed */
-		buff += additional_bytes_needed;
-		bytes_left -= additional_bytes_needed;
-
-		/* Since data has been process mark it as zero */
-		data->count = 0;
-	}
-
-
-	/* Process this buffer in full chunks */
-	while (bytes_left >= a2dp->codesize) {
-		/* Enough data to encode (sbc wants 1k blocks) */
-		encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize,
-					a2dp->buffer + a2dp->count,
-					sizeof(a2dp->buffer) - a2dp->count,
-								&written);
-		if (encoded <= 0) {
-			DBG("Encoding error %d", encoded);
-			goto done;
-		}
-
-		/* Increment up buff pointer to take into account
-		 * the data processed */
-		buff += a2dp->codesize;
-		bytes_left -= a2dp->codesize;
-
-		/* Increment a2dp buffers */
-		a2dp->count += written;
-		a2dp->frame_count++;
-		a2dp->samples += encoded / frame_size;
-		a2dp->nsamples += encoded / frame_size;
-
-		/* No space left for another frame then send */
-		if (a2dp->count + written >= data->link_mtu) {
-			avdtp_write(data);
-			DBG("sending packet %d, count %d, link_mtu %u",
-						a2dp->seq_num, a2dp->count,
-							data->link_mtu);
-		}
-	}
-
-out:
-	/* Copy the extra to our temp buffer for the next write */
-	if (bytes_left > 0) {
-		memcpy(data->buffer + data->count, buff, bytes_left);
-		data->count += bytes_left;
-		bytes_left = 0;
-	}
-
-done:
-	DBG("returning %ld", size - bytes_left / frame_size);
-
-	return size - bytes_left / frame_size;
-}
-
-static int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
-					snd_pcm_sframes_t *delayp)
-{
-	DBG("");
-
-	/* This updates io->hw_ptr value using pointer() function */
-	snd_pcm_hwsync(io->pcm);
-
-	*delayp = io->appl_ptr - io->hw_ptr;
-	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
-		io->callback->stop(io);
-		io->state = SND_PCM_STATE_XRUN;
-		*delayp = 0;
-	}
-
-	/* This should never fail, ALSA API is really not
-	prepared to handle a non zero return value */
-	return 0;
-}
-
-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_count	= bluetooth_playback_poll_descriptors_count,
-	.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,
-};
-
-static snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
-	.start			= bluetooth_playback_start,
-	.stop			= bluetooth_playback_stop,
-	.pointer		= bluetooth_pointer,
-	.close			= bluetooth_close,
-	.hw_params		= bluetooth_a2dp_hw_params,
-	.prepare		= bluetooth_prepare,
-	.transfer		= bluetooth_a2dp_write,
-	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
-	.poll_descriptors	= bluetooth_playback_poll_descriptors,
-	.poll_revents		= bluetooth_playback_poll_revents,
-	.delay			= bluetooth_playback_delay,
-};
-
-static snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
-	.start			= bluetooth_start,
-	.stop			= bluetooth_stop,
-	.pointer		= bluetooth_pointer,
-	.close			= bluetooth_close,
-	.hw_params		= bluetooth_a2dp_hw_params,
-	.prepare		= bluetooth_prepare,
-	.transfer		= bluetooth_a2dp_read,
-	.poll_descriptors	= bluetooth_poll_descriptors,
-	.poll_revents		= bluetooth_poll_revents,
-};
-
-#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;
-	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
-	};
-	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;
-
-	/* supported formats */
-	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 */
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
-							1, 1);
-	if (err < 0)
-		return err;
-
-	/* supported rate */
-	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_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,
-						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)
-		return err;
-
-	return 0;
-}
-
-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 bluetooth_alsa_config *cfg = &data->alsa_config;
-	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
-	};
-	unsigned int rate_list[4];
-	unsigned int rate_count;
-	int err, min_channels, max_channels;
-	unsigned int period_list[] = {
-		2048,
-		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
-		8192
-	};
-
-	/* 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;
-
-	/* supported formats */
-	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 */
-	if (cfg->has_channel_mode)
-		a2dp->sbc_capabilities.channel_mode = cfg->channel_mode;
-
-	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,
-							min_channels, max_channels);
-	if (err < 0)
-		return err;
-
-	/* supported buffer sizes
-	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
-	err = snd_pcm_ioplug_set_param_minmax(io,
-						SND_PCM_IOPLUG_HW_BUFFER_BYTES,
-						8192*3, 8192*3);
-	if (err < 0)
-		return err;
-
-	/* supported block sizes: */
-	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
-				ARRAY_NELEMS(period_list), period_list);
-	if (err < 0)
-		return err;
-
-	/* supported rates */
-	rate_count = 0;
-	if (cfg->has_rate) {
-		rate_list[rate_count] = cfg->rate;
-		rate_count++;
-	} else {
-		if (a2dp->sbc_capabilities.frequency &
-				BT_SBC_SAMPLING_FREQ_16000) {
-			rate_list[rate_count] = 16000;
-			rate_count++;
-		}
-
-		if (a2dp->sbc_capabilities.frequency &
-				BT_SBC_SAMPLING_FREQ_32000) {
-			rate_list[rate_count] = 32000;
-			rate_count++;
-		}
-
-		if (a2dp->sbc_capabilities.frequency &
-				BT_SBC_SAMPLING_FREQ_44100) {
-			rate_list[rate_count] = 44100;
-			rate_count++;
-		}
-
-		if (a2dp->sbc_capabilities.frequency &
-				BT_SBC_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;
-
-	return 0;
-}
-
-static int bluetooth_parse_config(snd_config_t *conf,
-				struct bluetooth_alsa_config *bt_config)
-{
-	snd_config_iterator_t i, next;
-
-	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
-
-	/* Set defaults */
-	bt_config->autoconnect = 1;
-
-	snd_config_for_each(i, next, conf) {
-		snd_config_t *n = snd_config_iterator_entry(i);
-		const char *id, *value;
-
-		if (snd_config_get_id(n, &id) < 0)
-			continue;
-
-		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
-			continue;
-
-		if (strcmp(id, "autoconnect") == 0) {
-			int b;
-
-			b = snd_config_get_bool(n);
-			if (b < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->autoconnect = b;
-			continue;
-		}
-
-		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
-			if (snd_config_get_string(n, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->has_device = 1;
-			strncpy(bt_config->device, value, 18);
-			continue;
-		}
-
-		if (strcmp(id, "profile") == 0) {
-			if (snd_config_get_string(n, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			if (strcmp(value, "auto") == 0) {
-				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
-				bt_config->has_transport = 1;
-			} else if (strcmp(value, "voice") == 0 ||
-						strcmp(value, "hfp") == 0) {
-				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
-				bt_config->has_transport = 1;
-			} else if (strcmp(value, "hifi") == 0 ||
-						strcmp(value, "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, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->rate = atoi(value);
-			bt_config->has_rate = 1;
-			continue;
-		}
-
-		if (strcmp(id, "mode") == 0) {
-			if (snd_config_get_string(n, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			if (strcmp(value, "mono") == 0) {
-				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
-				bt_config->has_channel_mode = 1;
-			} else if (strcmp(value, "dual") == 0) {
-				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
-				bt_config->has_channel_mode = 1;
-			} else if (strcmp(value, "stereo") == 0) {
-				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
-				bt_config->has_channel_mode = 1;
-			} else if (strcmp(value, "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, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			if (strcmp(value, "loudness") == 0) {
-				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
-				bt_config->has_allocation_method = 1;
-			} else if (strcmp(value, "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, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->subbands = atoi(value);
-			bt_config->has_subbands = 1;
-			continue;
-		}
-
-		if (strcmp(id, "blocks") == 0) {
-			if (snd_config_get_string(n, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->block_length = atoi(value);
-			bt_config->has_block_length = 1;
-			continue;
-		}
-
-		if (strcmp(id, "bitpool") == 0) {
-			if (snd_config_get_string(n, &value) < 0) {
-				SNDERR("Invalid type for %s", id);
-				return -EINVAL;
-			}
-
-			bt_config->bitpool = atoi(value);
-			bt_config->has_bitpool = 1;
-			continue;
-		}
-
-		SNDERR("Unknown field %s", id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
-{
-	int err;
-	uint16_t length;
-
-	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
-
-	DBG("sending %s:%s", bt_audio_strtype(msg->type),
-		bt_audio_strname(msg->name));
-	if (send(sk, msg, length, 0) > 0)
-		err = 0;
-	else {
-		err = -errno;
-		SNDERR("Error sending data to audio service: %s(%d)",
-			strerror(-err), -err);
-	}
-
-	return err;
-}
-
-static int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
-{
-	int err;
-	ssize_t ret;
-	const char *type, *name;
-	uint16_t length;
-
-	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
-
-	DBG("trying to receive msg from audio service...");
-
-	ret = recv(sk, inmsg, length, 0);
-	if (ret < 0) {
-		err = -errno;
-		SNDERR("Error receiving IPC data from bluetoothd: %s (%d)",
-						strerror(-err), -err);
-	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
-		SNDERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
-		err = -EINVAL;
-	} else {
-		type = bt_audio_strtype(inmsg->type);
-		name = bt_audio_strname(inmsg->name);
-		if (type && name) {
-			DBG("Received %s - %s", type, name);
-			err = 0;
-		} else {
-			err = -EINVAL;
-			SNDERR("Bogus message type %d - name %d"
-					" received from audio service",
-					inmsg->type, inmsg->name);
-		}
-
-	}
-
-	return err;
-}
-
-static int audioservice_expect(int sk, bt_audio_msg_header_t *rsp,
-							int expected_name)
-{
-	bt_audio_error_t *error;
-	int err = audioservice_recv(sk, rsp);
-
-	if (err != 0)
-		return err;
-
-	if (rsp->name != expected_name) {
-		err = -EINVAL;
-		SNDERR("Bogus message %s received while %s was expected",
-				bt_audio_strname(rsp->name),
-				bt_audio_strname(expected_name));
-	}
-
-	if (rsp->type == BT_ERROR) {
-		error = (void *) rsp;
-		SNDERR("%s failed : %s(%d)",
-					bt_audio_strname(rsp->name),
-					strerror(error->posix_errno),
-					error->posix_errno);
-		return -error->posix_errno;
-	}
-
-	return err;
-}
-
-static int bluetooth_parse_capabilities(struct bluetooth_data *data,
-					struct bt_get_capabilities_rsp *rsp)
-{
-	int bytes_left = rsp->h.length - sizeof(*rsp);
-	codec_capabilities_t *codec = (void *) rsp->data;
-
-	data->transport = codec->transport;
-
-	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
-		return 0;
-
-	while (bytes_left > 0) {
-		if ((codec->type == BT_A2DP_SBC_SINK) &&
-				!(codec->lock & BT_WRITE_LOCK))
-			break;
-
-		bytes_left -= codec->length;
-		codec = (void *) codec + codec->length;
-	}
-
-	if (bytes_left <= 0 ||
-			codec->length != sizeof(data->a2dp.sbc_capabilities))
-		return -EINVAL;
-
-	memcpy(&data->a2dp.sbc_capabilities, codec, codec->length);
-
-	return 0;
-}
-
-static int bluetooth_init(struct bluetooth_data *data,
-				snd_pcm_stream_t stream, snd_config_t *conf)
-{
-	int sk, err;
-	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
-	char buf[BT_SUGGESTED_BUFFER_SIZE];
-	struct bt_get_capabilities_req *req = (void *) buf;
-	struct bt_get_capabilities_rsp *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 = 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) {
-		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(req, 0, BT_SUGGESTED_BUFFER_SIZE);
-	req->h.type = BT_REQUEST;
-	req->h.name = BT_GET_CAPABILITIES;
-	req->h.length = sizeof(*req);
-
-	if (alsa_conf->autoconnect)
-		req->flags |= BT_FLAG_AUTOCONNECT;
-	strncpy(req->destination, alsa_conf->device, 18);
-	if (alsa_conf->has_transport)
-		req->transport = alsa_conf->transport;
-	else
-		req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
-
-	err = audioservice_send(data->server.fd, &req->h);
-	if (err < 0)
-		goto failed;
-
-	rsp->h.length = 0;
-	err = audioservice_expect(data->server.fd, &rsp->h,
-					BT_GET_CAPABILITIES);
-	if (err < 0)
-		goto failed;
-
-	bluetooth_parse_capabilities(data, rsp);
-
-	return 0;
-
-failed:
-	if (sk >= 0)
-		bt_audio_service_close(sk);
-	return err;
-}
-
-SND_PCM_PLUGIN_DEFINE_FUNC(bluetooth);
-
-SND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
-{
-	struct bluetooth_data *data;
-	int err;
-
-	DBG("Bluetooth PCM plugin (%s)",
-		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
-
-	data = malloc(sizeof(struct bluetooth_data));
-	if (!data) {
-		err = -ENOMEM;
-		goto error;
-	}
-
-	err = bluetooth_init(data, stream, conf);
-	if (err < 0)
-		goto error;
-
-	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->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->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);
-		goto error;
-	}
-
-	*pcmp = data->io.pcm;
-
-	return 0;
-
-error:
-	if (data)
-		bluetooth_exit(data);
-
-	return err;
-}
-
-SND_PCM_PLUGIN_SYMBOL(bluetooth);
diff --git a/configure.ac b/configure.ac
index f2db920..7f331ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,7 +41,6 @@ AC_CHECK_HEADER([sys/inotify.h],
 			[AC_MSG_ERROR(inotify headers are required and missing)])
 AC_PATH_DBUS
 AC_PATH_GLIB
-AC_PATH_ALSA
 AC_PATH_GSTREAMER
 AC_PATH_USB
 AC_PATH_UDEV
-- 
1.7.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Bluez Devel]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Bluez Devel]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Big List of Linux Books]

Add to Google Powered by Linux