1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/*
2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
55592142cb9383df0556b27ac59e96547b380310bJohan Hedberg *  Copyright (C) 2006-2010  Nokia Corporation
69184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
8e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
9e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  This library is free software; you can redistribute it and/or
10e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  modify it under the terms of the GNU Lesser General Public
11e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  License as published by the Free Software Foundation; either
12e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  version 2.1 of the License, or (at your option) any later version.
13e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
14e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  This library is distributed in the hope that it will be useful,
15e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Lesser General Public License for more details.
18e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
19e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  You should have received a copy of the GNU Lesser General Public
20e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  License along with this library; if not, write to the Free Software
21e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
23e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann */
24e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann
25e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#ifdef HAVE_CONFIG_H
26e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#include <config.h>
27e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#endif
285ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
29714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#include <stdint.h>
30b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/socket.h>
31b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/un.h>
32344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg#include <time.h>
336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <sys/time.h>
34e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg#include <pthread.h>
35dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg#include <signal.h>
36a1ddddc934657aa734ceb4bf581423647cc68060Marcel Holtmann#include <limits.h>
376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h>
39b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
405ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h>
415ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h>
425ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
43b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h"
446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h"
45347675ea994642c0ccd60f7af70f369f7a2d7a88Luiz Augusto von Dentz#include "rtp.h"
466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
473d586da1dd17ca73a4bd4a5cad9284a331860042Szymon Janc/* #define ENABLE_DEBUG */
486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
49714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#define UINT_SECS_MAX (UINT_MAX / 1000000 - 1)
50714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg
51e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz#define MIN_PERIOD_TIME 1
52714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg
53f5befe8ab54b797a0a5357ceddf2f05ab0ff163cJohan Hedberg#define BUFFER_SIZE 2048
54b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
55f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG
56b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
57f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else
58f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...)
59f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif
60b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
6197c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#ifndef SOL_SCO
6297c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#define SOL_SCO 17
6397c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#endif
6497c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann
658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS
668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03
678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS
708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04
718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MIN
742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MIN(x, y) ((x) < (y) ? (x) : (y))
752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif
762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MAX
782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MAX(x, y) ((x) > (y) ? (x) : (y))
792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif
802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MAX_BITPOOL 64
822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MIN_BITPOOL 2
832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
84d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg/* adapted from glibc sys/time.h timersub() macro */
85d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg#define priv_timespecsub(a, b, result)					\
86d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	do {								\
87d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;		\
88d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;	\
89d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		if ((result)->tv_nsec < 0) {				\
90d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			--(result)->tv_sec;				\
91d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			(result)->tv_nsec += 1000000000;		\
92d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		}							\
93d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	} while (0)
94344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg
956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp {
96d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_capabilities_t sbc_capabilities;
97d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_t sbc;				/* Codec data */
98d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int sbc_initialized;			/* Keep track if the encoder is initialized */
990d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int codesize;			/* SBC codesize */
100d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int samples;				/* Number of encoded samples */
101d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
1020d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int count;			/* Codec transfer buffer counter */
103d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
104d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int nsamples;				/* Cumulative number of codec samples */
105d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint16_t seq_num;			/* Cumulative packet sequence */
106d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int frame_count;			/* Current frames in buffer*/
107d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz};
108d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
109d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstruct bluetooth_alsa_config {
110d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char device[18];		/* Address of the remote Device */
111d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_device;
112d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t transport;		/* Requested transport */
113d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_transport;
114d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint16_t rate;
115d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_rate;
116d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t channel_mode;		/* A2DP only */
117d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_channel_mode;
118d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t allocation_method;	/* A2DP only */
119d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_allocation_method;
120d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t subbands;		/* A2DP only */
121d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_subbands;
122d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t block_length;		/* A2DP only */
123d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_block_length;
124d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t bitpool;		/* A2DP only */
125d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_bitpool;
1269fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	int autoconnect;
1276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
1286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data {
130b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_ioplug_t io;
131d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config alsa_config;	/* ALSA resource file parameters */
132e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	volatile snd_pcm_sframes_t hw_ptr;
133d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int transport;					/* chosen transport SCO or AD2P */
1340d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int link_mtu;				/* MTU for selected transport channel */
135d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	volatile struct pollfd stream;			/* Audio stream filedescriptor */
136d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct pollfd server;				/* Audio daemon filedescriptor */
137d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t buffer[BUFFER_SIZE];		/* Encoded transfer buffer */
1380d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int count;				/* Transfer buffer counter */
139d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp a2dp;			/* A2DP data */
140d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
141d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	pthread_t hw_thread;				/* Makes virtual hw pointer move */
142d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int pipefd[2];					/* Inter thread communication */
143892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	int stopped;
144cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	sig_atomic_t reset;				/* Request XRUN handling */
145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
146b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
147d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg);
148d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg,
149a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann							int expected_type);
150d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
151b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io)
152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1539217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_start %p", io);
154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
156b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io)
159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1609217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_stop %p", io);
161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
163b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
164b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
165892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic void *playback_hw_thread(void *param)
166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = param;
168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	unsigned int prev_periods;
169e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	double period_time;
170d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	struct timespec start;
171e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	struct pollfd fds[2];
1723e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	int poll_timeout;
173e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
174dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->server.events = POLLIN;
175dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	/* note: only errors for data->stream.events */
176dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
177e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[0] = data->server;
178e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[1] = data->stream;
179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	prev_periods = 0;
181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	period_time = 1000000.0 * data->io.period_size / data->io.rate;
1823e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	if (period_time > (int) (MIN_PERIOD_TIME * 1000))
1833e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = (int) (period_time / 1000.0f);
1843e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	else
1853e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = MIN_PERIOD_TIME;
186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
187d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	clock_gettime(CLOCK_MONOTONIC, &start);
188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
189e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	while (1) {
190714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg		unsigned int dtime, periods;
191d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		struct timespec cur, delta;
192e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		int ret;
193e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
194892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (data->stopped)
195f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg			goto iter_sleep;
196f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
197dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (data->reset) {
198dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Handle XRUN in hw-thread.");
199dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->reset = 0;
200d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			clock_gettime(CLOCK_MONOTONIC, &start);
201dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			prev_periods = 0;
202dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
203dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
204d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		clock_gettime(CLOCK_MONOTONIC, &cur);
205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
206d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		priv_timespecsub(&cur, &start, &delta);
207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
208d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000;
209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		periods = 1.0 * dtime / period_time;
210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		if (periods > prev_periods) {
212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			char c = 'w';
213dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			int frags = periods - prev_periods, n;
214e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
215dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->hw_ptr += frags *	data->io.period_size;
216e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			data->hw_ptr %= data->io.buffer_size;
217e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
218dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			for (n = 0; n < frags; n++) {
219dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				/* Notify user that hardware pointer
220dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				 * has moved * */
221dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				if (write(data->pipefd[1], &c, 1) < 0)
222dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					pthread_testcancel();
223dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			}
224e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
225714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			/* Reset point of reference to avoid too big values
226714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			 * that wont fit an unsigned int */
227b47d1eeb490aa518b0bafb0fe5d968e4ef313e60Marcel Holtmann			if ((unsigned int) delta.tv_sec < UINT_SECS_MAX)
2288dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg				prev_periods = periods;
2298dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			else {
230714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg				prev_periods = 0;
231d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg				clock_gettime(CLOCK_MONOTONIC, &start);
2328dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			}
233de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		}
234e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
235f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedbergiter_sleep:
2363e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		/* sleep up to one period interval */
2373e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		ret = poll(fds, 2, poll_timeout);
238dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
239e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		if (ret < 0) {
24050c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier			if (errno != EINTR) {
24150c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier				SNDERR("poll error: %s (%d)", strerror(errno),
24250c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier								errno);
243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
24450c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier			}
245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		} else if (ret > 0) {
246e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			ret = (fds[0].revents) ? 0 : 1;
247e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll fd %d revents %d", ret, fds[ret].revents);
248db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann			if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL))
249e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
250e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		}
251e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
252e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		/* Offer opportunity to be canceled by main thread */
253de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		pthread_testcancel();
254e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
255e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
256e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->hw_thread = 0;
257e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pthread_exit(NULL);
258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
25933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
260892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io)
261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
263e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int err;
264e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
265e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
266e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
267892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 0;
268f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
269892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread)
270f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		return 0;
271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
272892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
273e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return -err;
275e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
277892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
279e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
281e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
283892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 1;
284e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
2857090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg	return 0;
286e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
287e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return data->hw_ptr;
293b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
294b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
2955ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data)
2965ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{
297892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
298892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
299e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->server.fd >= 0)
300d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		bt_audio_service_close(data->server.fd);
3015ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
302e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->stream.fd >= 0)
303e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		close(data->stream.fd);
3042a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz
305892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread) {
306892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
307892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
308892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
309f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
310d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
311f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		sbc_finish(&a2dp->sbc);
312d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz
313892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[0] > 0)
314892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[0]);
315de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
316892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[1] > 0)
317892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[1]);
318de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
3195ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	free(data);
3205ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz}
3215ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
322b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io)
323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
324b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("%p", io);
327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3285ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
329b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
330b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
331b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
332b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io)
3348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
3358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
336e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	char c = 'w';
3371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
338cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_start_stream_req *req = (void *) buf;
339cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_start_stream_rsp *rsp = (void *) buf;
340cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_new_stream_ind *ind = (void *) buf;
341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int opt_name, err;
343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct timeval t = { 0, period_count };
3448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
34538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
34638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					io->period_size, io->buffer_size);
3478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
348dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->reset = 0;
349dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* As we're gonna receive messages on the server socket, we have to stop the
351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	   hw thread that is polling on it, if any */
352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->hw_thread) {
353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
355d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->hw_thread = 0;
356d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
357d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	if (io->stream == SND_PCM_STREAM_PLAYBACK)
35900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* If not null for playback, xmms doesn't display time
36000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * correctly */
3618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = 0;
3629217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	else
36300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* ALSA library is really picky on the fact hw_ptr is not null.
36400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * If it is, capture won't start */
3658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = io->period_size;
3669217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* send start */
3681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
3691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.type = BT_REQUEST;
3701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.name = BT_START_STREAM;
3711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.length = sizeof(*req);
3728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
3731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &req->h);
374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3771c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = sizeof(*rsp);
3781c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
3791c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_START_STREAM);
380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3831c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	ind->h.length = sizeof(*ind);
3841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &ind->h,
3851c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_NEW_STREAM);
386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd >= 0)
390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		close(data->stream.fd);
391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd < 0) {
394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return -errno;
395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
3969217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
399d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						SO_SNDTIMEO : SO_RCVTIMEO;
400ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							sizeof(t)) < 0)
403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return -errno;
404d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
405d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
40638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SCO_TXBUFS : SCO_RXBUFS;
4078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
40938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4119217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
412d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
41338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SO_SNDBUF : SO_RCVBUF;
41400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
41638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4187090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg
419d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		/* FIXME : handle error codes */
420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
42100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* wake up any client polling at us */
423165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	err = write(data->pipefd[1], &c, 1);
424165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	if (err < 0)
425165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann		return err;
426165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann
427165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	return 0;
4288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
4298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
432721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{
433721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
4341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
435bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_req *open_req = (void *) buf;
436bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_rsp *open_rsp = (void *) buf;
437cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
438cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	int err;
440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
442721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					io->period_size, io->buffer_size);
443721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
444450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
445bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.type = BT_REQUEST;
446bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.name = BT_OPEN;
447bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.length = sizeof(*open_req);
448bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
449bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	strncpy(open_req->destination, data->alsa_config.device, 18);
450bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->seid = BT_A2DP_SEID_RANGE + 1;
451bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
452bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz			BT_WRITE_LOCK : BT_READ_LOCK);
453bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
454bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &open_req->h);
455bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
456bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
457bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
458bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_rsp->h.length = sizeof(*open_rsp);
459bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &open_rsp->h,
460bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz					BT_OPEN);
461bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
462bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
463bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
464bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
465450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.type = BT_REQUEST;
466450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
467450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length = sizeof(*req);
4681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
469450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
470bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	req->codec.seid = BT_A2DP_SEID_RANGE + 1;
471450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.length = sizeof(pcm_capabilities_t);
472721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
473450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
474450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
475721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
476721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
477721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
478450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	rsp->h.length = sizeof(*rsp);
479450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
4801c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
481721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
482721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
483721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
484bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	data->transport = BT_CAPABILITIES_TRANSPORT_SCO;
485450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	data->link_mtu = rsp->link_mtu;
486721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
487721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	return 0;
488721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz}
489721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (freq) {
493489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_16000:
494489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_32000:
4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
496489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_44100:
4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 31;
5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
5062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
508489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_48000:
5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 29;
5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Invalid sampling freq %u", freq);
5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5242934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data,
527a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann					snd_pcm_hw_params_t *params)
5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
5298fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
5308fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities;
5318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	unsigned int max_bitpool, min_bitpool, rate, channels;
5328fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int dir;
5338fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
5348fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_rate(params, &rate, &dir);
5358fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_channels(params, &channels);
5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (rate) {
5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 48000:
539489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 44100:
542489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 32000:
545489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 16000:
548489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Rate %d not supported", rate);
5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5532934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5542934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
5568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->channel_mode = cfg->channel_mode;
5578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (channels == 2) {
5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	} else {
5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (!cap->channel_mode) {
5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported channel modes");
5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_block_length)
5758fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->block_length = cfg->block_length;
5768fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported block lengths");
5862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5872934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_subbands)
5908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->subbands = cfg->subbands;
5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->subbands & BT_A2DP_SUBBANDS_8)
5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_8;
5932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_4;
5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported subbands");
5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_allocation_method)
6018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->allocation_method = cfg->allocation_method;
6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
6052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_bitpool)
6088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = max_bitpool = cfg->bitpool;
6098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else {
6108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
6118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		max_bitpool = MIN(default_bitpool(cap->frequency,
6128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->channel_mode),
6138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->max_bitpool);
6148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	}
6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
6172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
6182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	return 0;
6202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
6212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp)
623afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
6248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
625afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
626d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
6272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_reinit(&a2dp->sbc, 0);
6282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else
6292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_init(&a2dp->sbc, 0);
630d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc_initialized = 1;
6312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
632489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
63323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_16000;
634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
635489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
63623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_32000;
637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
638489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
63923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_44100;
640d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
641489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
64223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_48000;
643d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
64523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_MONO;
646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
64723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
64823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
64923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
65123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_STEREO;
65223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
65323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
65423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.allocation = active_capabilities.allocation_method
65723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
65823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				: SBC_AM_LOUDNESS;
659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.subbands) {
661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_4:
66223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_4;
663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_8:
66523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_8;
666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.block_length) {
670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_4:
67123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_4;
672d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_8:
67423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_8;
675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_12:
67723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_12;
678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_16:
68023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_16;
681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
6858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
6878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz}
6888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
6908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
6918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{
6928fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
6938fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
6941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
695bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_req *open_req = (void *) buf;
696bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_rsp *open_rsp = (void *) buf;
697cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
698cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
6998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int err;
7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
7028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					io->period_size, io->buffer_size);
7038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
704bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
705bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.type = BT_REQUEST;
706bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.name = BT_OPEN;
707bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.length = sizeof(*open_req);
708bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
709bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	strncpy(open_req->destination, data->alsa_config.device, 18);
710bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->seid = a2dp->sbc_capabilities.capability.seid;
711bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
712bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz			BT_WRITE_LOCK : BT_READ_LOCK);
713bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
714bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &open_req->h);
715bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
716bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
717bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
718bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_rsp->h.length = sizeof(*open_rsp);
719bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &open_rsp->h,
720bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz					BT_OPEN);
721bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
722bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
723bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
7248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	err = bluetooth_a2dp_init(data, params);
7258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7278fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7281c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
7291c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
7301c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
7311c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
7321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
7331c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memcpy(&req->codec, &a2dp->sbc_capabilities,
7341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg			sizeof(a2dp->sbc_capabilities));
7351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
7361c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
7371c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.length = sizeof(a2dp->sbc_capabilities);
7381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
7398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
7418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7428fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7438fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7441c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = sizeof(*rsp);
7451c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
7461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
7478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
750bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	data->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
7511c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	data->link_mtu = rsp->link_mtu;
7528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	/* Setup SBC encoder now we agree on parameters */
7548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	bluetooth_a2dp_setup(a2dp);
755d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
756d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
758d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.bitpool);
759d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
760d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
761afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
762afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
764f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann					struct pollfd *pfd, unsigned int space)
765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(io);
769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
773e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pfd[0].fd = data->stream.fd;
774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
776e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
779e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
780e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
781e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg					struct pollfd *pfds, unsigned int nfds,
782dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds && nfds == 1 && revents);
785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = pfds[0].revents;
787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
789e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
790e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
79137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io)
79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{
79337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
79437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz}
79537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
796892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
79738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfd, unsigned int space)
798e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
799e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
800e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
801e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
803892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	assert(data->pipefd[0] >= 0);
804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
80537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (space < 2)
806e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
807e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
808892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	pfd[0].fd = data->pipefd[0];
809e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
810e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
81137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].fd = data->stream.fd;
81237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].events = POLLERR | POLLHUP | POLLNVAL;
81337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].revents = 0;
814e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
81537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
816e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
817e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
818892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
81938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfds, unsigned int nfds,
820dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
821e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
822e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	static char buf[1];
823e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
824e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
825e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
826e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds);
82737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(nfds == 2);
828e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(revents);
829e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds[0].fd >= 0);
83037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(pfds[1].fd >= 0);
831e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
832e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (io->state != SND_PCM_STATE_PREPARED)
83310a0350126bb517c36ac1d0d95e4995b6e303d8fSzymon Janc		if (read(pfds[0].fd, buf, 1) < 0)
83410a0350126bb517c36ac1d0d95e4995b6e303d8fSzymon Janc			SYSERR("read error: %s (%d)", strerror(errno), errno);
835e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
83637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
83737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz		io->state = SND_PCM_STATE_DISCONNECTED;
83837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
839593bd41ed861d80f498fa8cfe0cea06e0c11f442Johan Hedberg	*revents = (pfds[0].revents & POLLIN) ? POLLOUT : 0;
840e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
841e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
842e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
843e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
844e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
84638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
847dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
848dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
85100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
85200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
8530d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int frame_size = 0;
8540d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	int nrecv;
8558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
85638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
85738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8593709666344736da68472f754ac52edc356039058Johan Hedberg	frame_size = areas->step / 8;
8603709666344736da68472f754ac52edc356039058Johan Hedberg
86100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
86200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
86300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
864d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
865474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg					io->nonblock ? MSG_DONTWAIT : 0);
86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
86700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
86800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
86900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
8720d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	if ((unsigned int) nrecv != data->link_mtu) {
87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
87400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
87500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
87800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
879d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
880721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz				io->buffer_size;
88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88200c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
8836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
8846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
886d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
88700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
88800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
889d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_write = (data->link_mtu - data->count) / frame_size;
89000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
891f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
892f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
893d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->count %= data->link_mtu;
89400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
89500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
89600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
89700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
89800c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
89900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
9008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
9018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
9028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
90438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
905dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
906dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
9078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
9088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
9098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
9108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
911c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
912f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
9138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
91438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
91538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
9168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
917892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (io->hw_ptr > io->appl_ptr) {
918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
919892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (ret == 0)
920892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz			ret = -EPIPE;
921892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		goto done;
922892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
923892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
924f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
925d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
9268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
9278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
928d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_read = (data->link_mtu - data->count) / frame_size;
9298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
93038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
931c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
9328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
935f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
9368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
9382a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
939d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->count != data->link_mtu) {
9408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
94100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
9428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
9438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
944d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
945c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
94600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
94700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
94800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
94900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
95000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
95100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
95200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
95300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
95400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
95500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
95600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
957892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	DBG("returning %ld", ret);
9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
96238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
963a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
9666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
969e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data)
9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
971e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret = 0;
9726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
9749494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
9776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
9786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
9806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
9826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
9836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
9856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
9866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
9876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
988bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
989dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret < 0) {
990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("send returned %d errno %s.", ret, strerror(errno));
991e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = -errno;
992dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
9938905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg
9946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
9966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
9986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
9996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1000f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg	return ret;
10016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
10026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
100438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
100538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
10066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
10076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
10086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
10096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
10100d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int bytes_left;
1011c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering	int frame_size, encoded;
101265c9310f96fa78980196002fdf11e8d30b4fe6b6Johan Hedberg	ssize_t written;
10136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
10146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
101538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
101638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				areas->step, areas->first, offset, size);
1017dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
1018dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			io->appl_ptr - io->hw_ptr);
1019e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
1020bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Calutate starting pointers */
1021bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	frame_size = areas->step / 8;
1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	bytes_left = size * frame_size;
1023bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	buff = (uint8_t *) areas->addr +
1024bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann				(areas->first + areas->step * (offset)) / 8;
1025bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1026bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check for underrun */
1027cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->hw_ptr > io->appl_ptr) {
1028892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
1029de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		if (ret == 0)
1030e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			ret = -EPIPE;
1031dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->reset = 1;
1032bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		return ret;
1033de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz	}
1034e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
1035e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	/* Check if we should autostart */
1036cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->state == SND_PCM_STATE_PREPARED) {
1037e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_t *swparams;
1038e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_uframes_t threshold;
1039de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
1040e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_malloc(&swparams);
104138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
1042dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				!snd_pcm_sw_params_get_start_threshold(swparams,
1043dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg								&threshold)) {
1044cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg			if (io->appl_ptr >= threshold) {
1045e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg				ret = snd_pcm_start(io->pcm);
1046cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg				if (ret != 0)
1047bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					return ret;
1048e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			}
1049e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		}
1050dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1051de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		snd_pcm_sw_params_free(swparams);
1052e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
10536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check if we have any left over data from the last write */
105569b0d50a87f9786562de76c42045629b29304b27Colin Didier	if (data->count > 0) {
105669b0d50a87f9786562de76c42045629b29304b27Colin Didier		unsigned int additional_bytes_needed =
105769b0d50a87f9786562de76c42045629b29304b27Colin Didier						a2dp->codesize - data->count;
105869b0d50a87f9786562de76c42045629b29304b27Colin Didier		if (additional_bytes_needed > bytes_left)
105969b0d50a87f9786562de76c42045629b29304b27Colin Didier			goto out;
10606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1061dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		memcpy(data->buffer + data->count, buff,
1062bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						additional_bytes_needed);
10636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1064dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Enough data to encode (sbc wants 1k blocks) */
1065bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize,
1066fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					a2dp->buffer + a2dp->count,
1067fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					sizeof(a2dp->buffer) - a2dp->count,
1068bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1069dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (encoded <= 0) {
1070dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Encoding error %d", encoded);
1071dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1072dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1074bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1075397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->count += written;
1076397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->frame_count++;
1077397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->samples += encoded / frame_size;
1078397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->nsamples += encoded / frame_size;
10796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1080397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		/* No space left for another frame then send */
1081d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (a2dp->count + written >= data->link_mtu) {
1082dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			avdtp_write(data);
1083d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("sending packet %d, count %d, link_mtu %u",
1084d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					a2dp->seq_num, a2dp->count,
1085bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1086bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += additional_bytes_needed;
1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= additional_bytes_needed;
1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1093bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Since data has been process mark it as zero */
1094bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count = 0;
1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1098bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Process this buffer in full chunks */
1099bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	while (bytes_left >= a2dp->codesize) {
1100bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Enough data to encode (sbc wants 1k blocks) */
1101bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize,
1102bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					a2dp->buffer + a2dp->count,
1103bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					sizeof(a2dp->buffer) - a2dp->count,
1104bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1105bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (encoded <= 0) {
1106bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			DBG("Encoding error %d", encoded);
1107bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			goto done;
1108f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg		}
11096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1110bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1111bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1112bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += a2dp->codesize;
1113bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= a2dp->codesize;
1114bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1115bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1116bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->count += written;
1117bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->frame_count++;
1118bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->samples += encoded / frame_size;
1119bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->nsamples += encoded / frame_size;
1120bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1121bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* No space left for another frame then send */
1122bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (a2dp->count + written >= data->link_mtu) {
1123bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			avdtp_write(data);
11248a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg			DBG("sending packet %d, count %d, link_mtu %u",
1125bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						a2dp->seq_num, a2dp->count,
1126bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1127bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1128dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
1129dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
113069b0d50a87f9786562de76c42045629b29304b27Colin Didierout:
1131bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Copy the extra to our temp buffer for the next write */
1132bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	if (bytes_left > 0) {
1133bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		memcpy(data->buffer + data->count, buff, bytes_left);
1134bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count += bytes_left;
1135bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left = 0;
1136bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
11376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
1139bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	DBG("returning %ld", size - bytes_left / frame_size);
1140bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1141bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	return size - bytes_left / frame_size;
11428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
11438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
11446967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
11456967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg					snd_pcm_sframes_t *delayp)
1146a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{
1147a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	DBG("");
1148a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
1149a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This updates io->hw_ptr value using pointer() function */
1150a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	snd_pcm_hwsync(io->pcm);
11516967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1152a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	*delayp = io->appl_ptr - io->hw_ptr;
1153a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
1154a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->callback->stop(io);
1155a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->state = SND_PCM_STATE_XRUN;
1156a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		*delayp = 0;
1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	}
11586967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1159a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This should never fail, ALSA API is really not
1160a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	prepared to handle a non zero return value */
1161a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	return 0;
1162a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley}
1163a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
11646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
1165892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1166892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1169721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1170e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1171e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_write,
117237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1173892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1174892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1175a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
1179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1182e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1183721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1184e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1185e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_read,
1186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1188b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1189b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
11906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
1191892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1192892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1193e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1194e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1195e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1196e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1197e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_write,
119837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1199892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1200892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1201a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
12026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
12036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
12046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
1205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_read,
1212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1213e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1214b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1215b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
121833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
1219b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1220c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1221b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
1222b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
1223b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
1224b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
1225b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
1226b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
1227b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1228b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
1229a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka		SND_PCM_FORMAT_S16
1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1231d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1232b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1233c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
1234b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1235b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
1236b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1237b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1238b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1239c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
1240b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1241b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
1242b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1243b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1244b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1245c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
1246c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1247d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							1, 1);
1248b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1249b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1250b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
125135b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
1252c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1253d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							8000, 8000);
1254b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1255b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
125735b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
1258c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1259d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						data->link_mtu, data->link_mtu);
1260b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1261b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1262b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1263c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1264f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann									2, 200);
126533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
126633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
126733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
126833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	return 0;
126933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz}
127033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
127133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{
127333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1274d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
12758fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
127633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	snd_pcm_access_t access_list[] = {
127733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_RW_INTERLEAVED,
127833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		/* Mmap access is really useless fo this driver, but we
127933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * support it because some pieces of software out there
128033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * insist on using it */
128133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_MMAP_INTERLEAVED
128233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
128333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	unsigned int format_list[] = {
1284a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka		SND_PCM_FORMAT_S16
128533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
1286d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_list[4];
1287d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_count;
1288d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err, min_channels, max_channels;
1289dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	unsigned int period_list[] = {
1290db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		2048,
1291db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
1292db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		8192
1293dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	};
129433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
129533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* access type */
129633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
129733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(access_list), access_list);
129833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
129933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
130033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
130133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported formats */
130233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
130333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(format_list), format_list);
130433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
130533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
130633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
130733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported channels */
13088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
13098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		a2dp->sbc_capabilities.channel_mode = cfg->channel_mode;
13108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
13118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode &
13128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			BT_A2DP_CHANNEL_MODE_MONO)
1313d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 1;
1314d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1315d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 2;
131633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
13178fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode &
13188fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			(~BT_A2DP_CHANNEL_MODE_MONO))
1319d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 2;
1320d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1321d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 1;
1322d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1323d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1324d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							min_channels, max_channels);
132533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
132633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
132733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1328db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported buffer sizes
1329db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
1330cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	err = snd_pcm_ioplug_set_param_minmax(io,
1331cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1332cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						8192*3, 8192*3);
133383a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg	if (err < 0)
133483a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg		return err;
133583a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg
1336db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported block sizes: */
1337db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1338db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg				ARRAY_NELEMS(period_list), period_list);
1339b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1340b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1341b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* supported rates */
1343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rate_count = 0;
13448fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_rate) {
13458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		rate_list[rate_count] = cfg->rate;
1346d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
13478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	} else {
13488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_16000) {
13508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 16000;
13518fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1353ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
13548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_32000) {
13568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 32000;
13578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13588fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1359ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
13608fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13618fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_44100) {
13628fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 44100;
13638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
136500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
13668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_48000) {
13688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 48000;
13698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13708fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1371d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
137200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
1374db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg						rate_count, rate_list);
1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1377e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
13786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
13796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
13806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf,
1382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				struct bluetooth_alsa_config *bt_config)
13836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
138492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_iterator_t i, next;
138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
1387ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg
13889fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	/* Set defaults */
13899fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	bt_config->autoconnect = 1;
13909fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
139192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_for_each(i, next, conf) {
139292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		snd_config_t *n = snd_config_iterator_entry(i);
1393d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg		const char *id, *value;
139492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
139592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (snd_config_get_id(n, &id) < 0)
139692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
139792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
139892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
139992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
140092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14019fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		if (strcmp(id, "autoconnect") == 0) {
1402a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			int b;
1403a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg
1404a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			b = snd_config_get_bool(n);
1405a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			if (b < 0) {
14069fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				SNDERR("Invalid type for %s", id);
14079fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				return -EINVAL;
14089fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			}
14099fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1410a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			bt_config->autoconnect = b;
14119fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			continue;
14129fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		}
14139fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1414b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
1415d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
141692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
141792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
141892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1419b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_device = 1;
1421d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			strncpy(bt_config->device, value, 18);
142292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
142392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
142492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1425b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "profile") == 0) {
1426d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
142792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
142892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
142992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1430b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1431d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (strcmp(value, "auto") == 0) {
1432d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1433d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1434d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "voice") == 0 ||
1435d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "hfp") == 0) {
1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1437d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1438d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "hifi") == 0 ||
1439d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "a2dp") == 0) {
1440d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1441d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
144392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
144492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
144592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "rate") == 0) {
1447d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1452d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->rate = atoi(value);
1453d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_rate = 1;
14545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
145741b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz		if (strcmp(id, "mode") == 0) {
1458d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "mono") == 0) {
1464d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
1465d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1466d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "dual") == 0) {
1467d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
1468d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1469d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "stereo") == 0) {
1470d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
1471d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1472d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "joint") == 0) {
1473d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
1474d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1475d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "allocation") == 0) {
1480d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14845402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "loudness") == 0) {
1486d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
1487d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1488d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "snr") == 0) {
1489d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
1490d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1491d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "subbands") == 0) {
1496d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
15005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1501d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->subbands = atoi(value);
1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_subbands = 1;
15035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
15045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
15055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
15065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "blocks") == 0) {
1507d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
15085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
15095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
15105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
15115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1512d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->block_length = atoi(value);
1513d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_block_length = 1;
15145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
15155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
15165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
15175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "bitpool") == 0) {
1518d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
15195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
15205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
15215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
15225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1523d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->bitpool = atoi(value);
1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_bitpool = 1;
15255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
15265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
15275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
152892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		SNDERR("Unknown field %s", id);
152992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		return -EINVAL;
153092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	}
153192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
15325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return 0;
15335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
15345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1535d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
15365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1537d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
15381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
15391c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
15401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
15416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1542a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz	DBG("sending %s:%s", bt_audio_strtype(msg->type),
1543a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz		bt_audio_strname(msg->name));
15441c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	if (send(sk, msg, length, 0) > 0)
1545d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = 0;
1546d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else {
1547d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1548d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error sending data to audio service: %s(%d)",
1549d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strerror(errno), errno);
15508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
1551b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1552d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1553d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
15546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1555d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
1556d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
15577c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	int err;
15587c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	ssize_t ret;
15591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	const char *type, *name;
15601c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
15611c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
15621c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
1563d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1564d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("trying to receive msg from audio service...");
15652f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg
15662f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	ret = recv(sk, inmsg, length, 0);
15672f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	if (ret < 0) {
15682f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		err = -errno;
15692f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		SNDERR("Error receiving IPC data from bluetoothd: %s (%d)",
15702f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg						strerror(errno), errno);
15717c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
15722f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		SNDERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
15732f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		err = -EINVAL;
15742f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	} else {
15751c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		type = bt_audio_strtype(inmsg->type);
15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		name = bt_audio_strname(inmsg->name);
15771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		if (type && name) {
15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			DBG("Received %s - %s", type, name);
1579d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = 0;
1580d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		} else {
1581d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
15821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			SNDERR("Bogus message type %d - name %d"
15832f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg					" received from audio service",
15841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					inmsg->type, inmsg->name);
1585d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
15862f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg
15876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
15888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1589d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1590d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
1591dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg
15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp,
1593a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann							int expected_name)
1594d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	bt_audio_error_t *error;
15961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int err = audioservice_recv(sk, rsp);
15971c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15981c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (err != 0)
15991c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return err;
16001c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->name != expected_name) {
16021c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		err = -EINVAL;
16031c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("Bogus message %s received while %s was expected",
16041c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(rsp->name),
16051c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(expected_name));
16061c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
16071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16081c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->type == BT_ERROR) {
16091c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		error = (void *) rsp;
16101c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("%s failed : %s(%d)",
16111c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					bt_audio_strname(rsp->name),
16121c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					strerror(error->posix_errno),
16131c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					error->posix_errno);
16141c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -error->posix_errno;
1615f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
16161c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1617d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
16188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
16198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
16201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
16211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					struct bt_get_capabilities_rsp *rsp)
16221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{
16231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int bytes_left = rsp->h.length - sizeof(*rsp);
16241c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	codec_capabilities_t *codec = (void *) rsp->data;
16251c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16261c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	data->transport = codec->transport;
16271c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16281c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
16291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return 0;
16301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16311c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	while (bytes_left > 0) {
1632379d756055f32d46fe7e09e1d89be1f780abb144Luiz Augusto von Dentz		if ((codec->type == BT_A2DP_SBC_SINK) &&
1633c5e75a5051967530f29f9fabfb8593ef2723d57eLuiz Augusto von Dentz				!(codec->lock & BT_WRITE_LOCK))
16341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			break;
16351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16361c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		bytes_left -= codec->length;
16371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		codec = (void *) codec + codec->length;
16381c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
16391c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (bytes_left <= 0 ||
16411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			codec->length != sizeof(data->a2dp.sbc_capabilities))
16421c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -EINVAL;
16431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	memcpy(&data->a2dp.sbc_capabilities, codec, codec->length);
16451c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	return 0;
16471c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz}
16481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1649a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmannstatic int bluetooth_init(struct bluetooth_data *data,
1650a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann				snd_pcm_stream_t stream, snd_config_t *conf)
16518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
16526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
1653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
16541c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
1655cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_req *req = (void *) buf;
1656cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_rsp *rsp = (void *) buf;
1657f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
165800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
165900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = bluetooth_parse_config(conf, alsa_conf);
1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1664e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = -1;
1665dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg	data->stream.fd = -1;
166600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sk = bt_audio_service_open();
1668e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley	if (sk <= 0) {
1669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1671b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1672b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1673e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = sk;
1674e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.events = POLLIN;
1675b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1676892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[0] = -1;
1677892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[1] = -1;
1678892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (pipe(data->pipefd) < 0) {
1680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
1684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1687d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
1688d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1689d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1690d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1691d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
16921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
16931c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
16941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_GET_CAPABILITIES;
16951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
16961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16979fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	if (alsa_conf->autoconnect)
16981c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->flags |= BT_FLAG_AUTOCONNECT;
16999bdf6ba0c50a3d5500e616b0f9d63a190692cc2cLuiz Augusto von Dentz	strncpy(req->destination, alsa_conf->device, 18);
1700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (alsa_conf->has_transport)
17011c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = alsa_conf->transport;
1702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
17031c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1704721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
17051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
1706d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1707d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1708d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
17091c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = 0;
17101c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
17111c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg					BT_GET_CAPABILITIES);
1712d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1713d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1714d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
17151c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	bluetooth_parse_capabilities(data, rsp);
1716892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1717d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
1718d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1719d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed:
17209d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg	if (sk >= 0)
17219d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg		bt_audio_service_close(sk);
1722d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
17238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
17248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1725ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth);
1726ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann
17278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
17288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1729f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
17308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
17318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
173200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
17338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
17348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1735d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg	data = malloc(sizeof(struct bluetooth_data));
173600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
173700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
173800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
173900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
174000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1741ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg	err = bluetooth_init(data, stream, conf);
17428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
17438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
17448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1745f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
1746f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
174700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
1748f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
1749b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1750d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
17516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
17526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
17536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
17546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
17556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
17566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
17576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
17586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1759f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
1760b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1761b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
1762b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1763d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
176433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_a2dp_hw_constraint(&data->io);
176533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	else
176633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_hsp_hw_constraint(&data->io);
176733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1768b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
1769f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
17708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
1771b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1772b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1773f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
1774b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1775b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
1776b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1777b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
177865aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg	if (data)
177965aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg		bluetooth_exit(data);
17805ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
1781b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
17825ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
17835ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
17845ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
1785