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
4738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann//#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) {
240e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll error: %s (%d)", strerror(errno), errno);
241e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			if (errno != EINTR)
242e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		} else if (ret > 0) {
244e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			ret = (fds[0].revents) ? 0 : 1;
245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll fd %d revents %d", ret, fds[ret].revents);
246db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann			if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL))
247e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
248e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		}
249e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
250e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		/* Offer opportunity to be canceled by main thread */
251de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		pthread_testcancel();
252e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
253e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
254e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->hw_thread = 0;
255e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pthread_exit(NULL);
256e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
25733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
258892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io)
259e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
260e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int err;
262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
263e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
264e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
265892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 0;
266f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
267892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread)
268f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		return 0;
269e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
270892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return -err;
273e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
275892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
277e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
279e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
281892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 1;
282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
2837090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg	return 0;
284e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
285e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return data->hw_ptr;
291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
2935ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data)
2945ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{
295892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
296892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
297e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->server.fd >= 0)
298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		bt_audio_service_close(data->server.fd);
2995ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
300e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->stream.fd >= 0)
301e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		close(data->stream.fd);
3022a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz
303892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread) {
304892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
305892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
306892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
307f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
309f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		sbc_finish(&a2dp->sbc);
310d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz
311892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[0] > 0)
312892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[0]);
313de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
314892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[1] > 0)
315892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[1]);
316de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
3175ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	free(data);
3185ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz}
3195ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io)
321b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
322b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("%p", io);
325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3265ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
328b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
329b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
330b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io)
3328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
3338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
334e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	char c = 'w';
3351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
336cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_start_stream_req *req = (void *) buf;
337cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_start_stream_rsp *rsp = (void *) buf;
338cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_new_stream_ind *ind = (void *) buf;
339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int opt_name, err;
341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct timeval t = { 0, period_count };
3428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
34338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
34438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					io->period_size, io->buffer_size);
3458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
346dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->reset = 0;
347dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
348d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* As we're gonna receive messages on the server socket, we have to stop the
349d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	   hw thread that is polling on it, if any */
350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->hw_thread) {
351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->hw_thread = 0;
354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
355d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3569217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	if (io->stream == SND_PCM_STREAM_PLAYBACK)
35700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* If not null for playback, xmms doesn't display time
35800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * correctly */
3598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = 0;
3609217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	else
36100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* ALSA library is really picky on the fact hw_ptr is not null.
36200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * If it is, capture won't start */
3638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = io->period_size;
3649217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* send start */
3661c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
3671c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.type = BT_REQUEST;
3681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.name = BT_START_STREAM;
3691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	req->h.length = sizeof(*req);
3708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
3711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &req->h);
372d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3751c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = sizeof(*rsp);
3761c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
3771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_START_STREAM);
378d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
379d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3811c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	ind->h.length = sizeof(*ind);
3821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &ind->h,
3831c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_NEW_STREAM);
384d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd >= 0)
388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		close(data->stream.fd);
389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd < 0) {
392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return -errno;
393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
3949217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						SO_SNDTIMEO : SO_RCVTIMEO;
398ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
399d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
400d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							sizeof(t)) < 0)
401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return -errno;
402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
40438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SCO_TXBUFS : SCO_RXBUFS;
4058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
406d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
40738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4099217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
41138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SO_SNDBUF : SO_RCVBUF;
41200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
413d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
41438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4167090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg
417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		/* FIXME : handle error codes */
418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
41900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* wake up any client polling at us */
421165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	err = write(data->pipefd[1], &c, 1);
422165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	if (err < 0)
423165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann		return err;
424165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann
425165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann	return 0;
4268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
4278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
428721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
429721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{
431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
4321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
433bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_req *open_req = (void *) buf;
434bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_rsp *open_rsp = (void *) buf;
435cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
436cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	int err;
438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					io->period_size, io->buffer_size);
441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
442450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
443bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.type = BT_REQUEST;
444bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.name = BT_OPEN;
445bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.length = sizeof(*open_req);
446bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
447bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	strncpy(open_req->destination, data->alsa_config.device, 18);
448bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->seid = BT_A2DP_SEID_RANGE + 1;
449bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
450bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz			BT_WRITE_LOCK : BT_READ_LOCK);
451bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
452bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &open_req->h);
453bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
454bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
455bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
456bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_rsp->h.length = sizeof(*open_rsp);
457bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &open_rsp->h,
458bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz					BT_OPEN);
459bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
460bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
461bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
462bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
463450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.type = BT_REQUEST;
464450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
465450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length = sizeof(*req);
4661c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
467450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
468bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	req->codec.seid = BT_A2DP_SEID_RANGE + 1;
469450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.length = sizeof(pcm_capabilities_t);
470721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
471450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
472450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
473721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
474721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
475721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
476450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	rsp->h.length = sizeof(*rsp);
477450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
4781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
479721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
480721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
481721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
482bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	data->transport = BT_CAPABILITIES_TRANSPORT_SCO;
483450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	data->link_mtu = rsp->link_mtu;
484721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
485721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	return 0;
486721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz}
487721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (freq) {
491489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_16000:
492489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_32000:
4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
494489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_44100:
4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 31;
4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
506489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_48000:
5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
5082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 29;
5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Invalid sampling freq %u", freq);
5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data,
525a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann					snd_pcm_hw_params_t *params)
5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
5278fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
5288fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities;
5298fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	unsigned int max_bitpool, min_bitpool, rate, channels;
5308fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int dir;
5318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
5328fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_rate(params, &rate, &dir);
5338fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_channels(params, &channels);
5342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (rate) {
5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 48000:
537489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 44100:
540489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 32000:
543489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 16000:
546489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Rate %d not supported", rate);
5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
5548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->channel_mode = cfg->channel_mode;
5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (channels == 2) {
5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	} else {
5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (!cap->channel_mode) {
5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported channel modes");
5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5728fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_block_length)
5738fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->block_length = cfg->block_length;
5748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported block lengths");
5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_subbands)
5888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->subbands = cfg->subbands;
5892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->subbands & BT_A2DP_SUBBANDS_8)
5902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_8;
5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_4;
5932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported subbands");
5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_allocation_method)
5998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->allocation_method = cfg->allocation_method;
6002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
6012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_bitpool)
6068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = max_bitpool = cfg->bitpool;
6078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else {
6088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
6098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		max_bitpool = MIN(default_bitpool(cap->frequency,
6108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->channel_mode),
6118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->max_bitpool);
6128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	}
6132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	return 0;
6182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
6192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6208fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp)
621afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
6228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
623afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
624d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
6252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_reinit(&a2dp->sbc, 0);
6262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else
6272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_init(&a2dp->sbc, 0);
628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc_initialized = 1;
6292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
630489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
63123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_16000;
632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
633489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
63423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_32000;
635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
636489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
63723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_44100;
638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
639489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
64023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_48000;
641d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
64323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_MONO;
644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
64523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
64623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
64723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
64823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
64923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_STEREO;
65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
65123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
65223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.allocation = active_capabilities.allocation_method
65523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
65623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				: SBC_AM_LOUDNESS;
657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.subbands) {
659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_4:
66023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_4;
661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_8:
66323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_8;
664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.block_length) {
668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_4:
66923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_4;
670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
671d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_8:
67223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_8;
673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_12:
67523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_12;
676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_16:
67823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_16;
679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
6838fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
6858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz}
6868fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
6888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
6898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{
6908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
6918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
6921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
693bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_req *open_req = (void *) buf;
694bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	struct bt_open_rsp *open_rsp = (void *) buf;
695cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
696cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
6978fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int err;
6988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					io->period_size, io->buffer_size);
7018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
702bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
703bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.type = BT_REQUEST;
704bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.name = BT_OPEN;
705bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->h.length = sizeof(*open_req);
706bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
707bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	strncpy(open_req->destination, data->alsa_config.device, 18);
708bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->seid = a2dp->sbc_capabilities.capability.seid;
709bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ?
710bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz			BT_WRITE_LOCK : BT_READ_LOCK);
711bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
712bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &open_req->h);
713bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
714bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
715bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
716bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	open_rsp->h.length = sizeof(*open_rsp);
717bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &open_rsp->h,
718bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz					BT_OPEN);
719bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	if (err < 0)
720bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz		return err;
721bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz
7228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	err = bluetooth_a2dp_init(data, params);
7238fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7261c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
7271c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
7281c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
7291c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
7301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
7311c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memcpy(&req->codec, &a2dp->sbc_capabilities,
7321c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg			sizeof(a2dp->sbc_capabilities));
7331c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
7341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
7351c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.length = sizeof(a2dp->sbc_capabilities);
7361c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
7378fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
7398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7408fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7421c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = sizeof(*rsp);
7431c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
7441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
7458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7468fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
748bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz	data->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
7491c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	data->link_mtu = rsp->link_mtu;
7508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7518fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	/* Setup SBC encoder now we agree on parameters */
7528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	bluetooth_a2dp_setup(a2dp);
753d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
754d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
755d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
756d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.bitpool);
757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
758d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
759afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
760afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
762f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann					struct pollfd *pfd, unsigned int space)
763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
764e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(io);
767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
771e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pfd[0].fd = data->stream.fd;
772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
773e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
776e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
779e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg					struct pollfd *pfds, unsigned int nfds,
780dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
781e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
782e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds && nfds == 1 && revents);
783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = pfds[0].revents;
785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
78937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io)
79037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{
79137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz}
79337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
794892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
79538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfd, unsigned int space)
796e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
797e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
798e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
799e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
800e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
801892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	assert(data->pipefd[0] >= 0);
802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
80337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (space < 2)
804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
805e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
806892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	pfd[0].fd = data->pipefd[0];
807e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
808e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
80937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].fd = data->stream.fd;
81037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].events = POLLERR | POLLHUP | POLLNVAL;
81137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].revents = 0;
812e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
81337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
814e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
815e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
816892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
81738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfds, unsigned int nfds,
818dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
819e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
820e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	static char buf[1];
821e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret;
822e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
823e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
824e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
825e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds);
82637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(nfds == 2);
827e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(revents);
828e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds[0].fd >= 0);
82937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(pfds[1].fd >= 0);
830e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
831e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (io->state != SND_PCM_STATE_PREPARED)
832e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = read(pfds[0].fd, buf, 1);
833e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
83437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
83537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz		io->state = SND_PCM_STATE_DISCONNECTED;
83637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
837593bd41ed861d80f498fa8cfe0cea06e0c11f442Johan Hedberg	*revents = (pfds[0].revents & POLLIN) ? POLLOUT : 0;
838e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
839e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
840e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
841e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
842e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
8436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
84438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
845dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
846dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
84900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
85000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
8510d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int frame_size = 0;
8520d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	int nrecv;
8538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
85438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
85538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8573709666344736da68472f754ac52edc356039058Johan Hedberg	frame_size = areas->step / 8;
8583709666344736da68472f754ac52edc356039058Johan Hedberg
85900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
86000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
86100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
862d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
863474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg					io->nonblock ? MSG_DONTWAIT : 0);
86400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
86500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
86700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
86900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
8700d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	if ((unsigned int) nrecv != data->link_mtu) {
87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
87200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
87600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
877d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
878721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz				io->buffer_size;
87900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88000c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
8816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
8826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
88300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
884d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
88600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
887d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_write = (data->link_mtu - data->count) / frame_size;
88800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
889f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
890f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
891d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->count %= data->link_mtu;
89200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
89300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
89400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
89500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
89600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
89700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
8988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
8998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
9008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
90238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
903dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
904dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
9058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
9068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
9078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
9088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
909c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
910f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
9118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
91238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
91338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
9148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
915892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (io->hw_ptr > io->appl_ptr) {
916892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
917892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (ret == 0)
918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz			ret = -EPIPE;
919892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		goto done;
920892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
921892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
922f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
923d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
9248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
9258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
926d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_read = (data->link_mtu - data->count) / frame_size;
9278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
92838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
929c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
9308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
9316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
933f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
9348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
9362a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
937d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->count != data->link_mtu) {
9388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
93900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
9408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
9418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
942d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
943c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
94400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
94500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
94600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
94700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
94800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
94900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
95000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
95100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
95200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
95300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
95400c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
955892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	DBG("returning %ld", ret);
9566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
96038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
961a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
9626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
967e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data)
9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
969e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret = 0;
9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
9716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
9729494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
9756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
9786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
9806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
9816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
9826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
9836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
9856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
986bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
987dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret < 0) {
988dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("send returned %d errno %s.", ret, strerror(errno));
989e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = -errno;
990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
9918905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg
9926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
9936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
9946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
9966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
998f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg	return ret;
9996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
10006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
100238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
100338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
10046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
10056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
10066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
10076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
10080d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann	unsigned int bytes_left;
1009c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering	int frame_size, encoded;
101065c9310f96fa78980196002fdf11e8d30b4fe6b6Johan Hedberg	ssize_t written;
10116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
10126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
101338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
101438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				areas->step, areas->first, offset, size);
1015dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
1016dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			io->appl_ptr - io->hw_ptr);
1017e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
1018bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Calutate starting pointers */
1019bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	frame_size = areas->step / 8;
1020bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	bytes_left = size * frame_size;
1021bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	buff = (uint8_t *) areas->addr +
1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann				(areas->first + areas->step * (offset)) / 8;
1023bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1024bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check for underrun */
1025cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->hw_ptr > io->appl_ptr) {
1026892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
1027de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		if (ret == 0)
1028e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			ret = -EPIPE;
1029dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->reset = 1;
1030bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		return ret;
1031de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz	}
1032e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
1033e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	/* Check if we should autostart */
1034cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->state == SND_PCM_STATE_PREPARED) {
1035e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_t *swparams;
1036e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_uframes_t threshold;
1037de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
1038e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_malloc(&swparams);
103938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
1040dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				!snd_pcm_sw_params_get_start_threshold(swparams,
1041dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg								&threshold)) {
1042cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg			if (io->appl_ptr >= threshold) {
1043e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg				ret = snd_pcm_start(io->pcm);
1044cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg				if (ret != 0)
1045bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					return ret;
1046e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			}
1047e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		}
1048dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1049de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		snd_pcm_sw_params_free(swparams);
1050e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
10516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1052bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check if we have any left over data from the last write */
1053bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	if (data->count > 0 && (bytes_left - data->count) >= a2dp->codesize) {
1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		int additional_bytes_needed = a2dp->codesize - data->count;
10556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1056dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		memcpy(data->buffer + data->count, buff,
1057bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						additional_bytes_needed);
10586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1059dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Enough data to encode (sbc wants 1k blocks) */
1060bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize,
1061fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					a2dp->buffer + a2dp->count,
1062fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					sizeof(a2dp->buffer) - a2dp->count,
1063bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1064dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (encoded <= 0) {
1065dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Encoding error %d", encoded);
1066dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1067dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1069bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1070397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->count += written;
1071397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->frame_count++;
1072397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->samples += encoded / frame_size;
1073397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->nsamples += encoded / frame_size;
10746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1075397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		/* No space left for another frame then send */
1076d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (a2dp->count + written >= data->link_mtu) {
1077dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			avdtp_write(data);
1078d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("sending packet %d, count %d, link_mtu %u",
1079d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					a2dp->seq_num, a2dp->count,
1080bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1081bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1082bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1083bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1084bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1085bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += additional_bytes_needed;
1086bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= additional_bytes_needed;
1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Since data has been process mark it as zero */
1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count = 0;
1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1093bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Process this buffer in full chunks */
1094bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	while (bytes_left >= a2dp->codesize) {
1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Enough data to encode (sbc wants 1k blocks) */
1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize,
1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					a2dp->buffer + a2dp->count,
1098bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					sizeof(a2dp->buffer) - a2dp->count,
1099bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1100bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (encoded <= 0) {
1101bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			DBG("Encoding error %d", encoded);
1102bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			goto done;
1103f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg		}
11046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1105bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1106bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1107bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += a2dp->codesize;
1108bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= a2dp->codesize;
1109bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1110bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1111bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->count += written;
1112bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->frame_count++;
1113bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->samples += encoded / frame_size;
1114bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->nsamples += encoded / frame_size;
1115bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1116bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* No space left for another frame then send */
1117bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (a2dp->count + written >= data->link_mtu) {
1118bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			avdtp_write(data);
11198a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg			DBG("sending packet %d, count %d, link_mtu %u",
1120bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						a2dp->seq_num, a2dp->count,
1121bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1122bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1123dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
1124dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1125bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Copy the extra to our temp buffer for the next write */
1126bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	if (bytes_left > 0) {
1127bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		memcpy(data->buffer + data->count, buff, bytes_left);
1128bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count += bytes_left;
1129bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left = 0;
1130bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
11316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
1133bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	DBG("returning %ld", size - bytes_left / frame_size);
1134bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1135bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	return size - bytes_left / frame_size;
11368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
11378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
11386967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
11396967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg					snd_pcm_sframes_t *delayp)
1140a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{
1141a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	DBG("");
1142a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
1143a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This updates io->hw_ptr value using pointer() function */
1144a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	snd_pcm_hwsync(io->pcm);
11456967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1146a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	*delayp = io->appl_ptr - io->hw_ptr;
1147a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
1148a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->callback->stop(io);
1149a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->state = SND_PCM_STATE_XRUN;
1150a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		*delayp = 0;
1151a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	}
11526967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1153a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This should never fail, ALSA API is really not
1154a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	prepared to handle a non zero return value */
1155a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	return 0;
1156a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley}
1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
11586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
1159892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1160892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1161e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1162e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1163721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_write,
116637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1167892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1168892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1169a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
1173e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1174e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1175e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1176e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1177721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_read,
1180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1182b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1183b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
11846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
1185892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1186892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1189e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1190e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1191e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_write,
119237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1193892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1194892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1195a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
1199e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1200e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1201e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1202e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1203e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1204e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_read,
1206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1208b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1209b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1210b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
1211b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
121233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
1213b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1214c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1215b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
1218b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
1219b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
1220b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
1221b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1222b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
1223a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka		SND_PCM_FORMAT_S16
1224b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1225d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1226b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1227c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
1228b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1229b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1231b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1232b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1233c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
1234b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1235b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
1236b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1237b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1238b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1239c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
1240c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1241d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							1, 1);
1242b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1243b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1244b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
124535b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
1246c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1247d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							8000, 8000);
1248b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1249b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1250b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
125135b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
1252c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1253d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						data->link_mtu, data->link_mtu);
1254b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1255b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1257c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1258f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann									2, 200);
125933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
126033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
126133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
126233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	return 0;
126333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz}
126433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
126533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
126633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{
126733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1268d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
12698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
127033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	snd_pcm_access_t access_list[] = {
127133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_RW_INTERLEAVED,
127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		/* Mmap access is really useless fo this driver, but we
127333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * support it because some pieces of software out there
127433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * insist on using it */
127533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_MMAP_INTERLEAVED
127633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
127733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	unsigned int format_list[] = {
1278a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka		SND_PCM_FORMAT_S16
127933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
1280d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_list[4];
1281d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_count;
1282d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err, min_channels, max_channels;
1283dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	unsigned int period_list[] = {
1284db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		2048,
1285db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
1286db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		8192
1287dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	};
128833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
128933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* access type */
129033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
129133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(access_list), access_list);
129233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
129333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
129433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
129533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported formats */
129633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
129733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(format_list), format_list);
129833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
129933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
130033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
130133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported channels */
13028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
13038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		a2dp->sbc_capabilities.channel_mode = cfg->channel_mode;
13048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
13058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode &
13068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			BT_A2DP_CHANNEL_MODE_MONO)
1307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 1;
1308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1309d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 2;
131033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz 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		max_channels = 2;
1314d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1315d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 1;
1316d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1317d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1318d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							min_channels, max_channels);
131933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
132033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
132133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1322db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported buffer sizes
1323db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
1324cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	err = snd_pcm_ioplug_set_param_minmax(io,
1325cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1326cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						8192*3, 8192*3);
132783a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg	if (err < 0)
132883a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg		return err;
132983a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg
1330db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported block sizes: */
1331db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1332db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg				ARRAY_NELEMS(period_list), period_list);
1333b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1334b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1335b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1336d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* supported rates */
1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rate_count = 0;
13388fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_rate) {
13398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		rate_list[rate_count] = cfg->rate;
1340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
13418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	} else {
13428fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13438fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_16000) {
13448fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 16000;
13458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13468fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1347ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
13488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_32000) {
13508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 32000;
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_44100) {
13568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 44100;
13578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13588fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
135900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
13608fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13618fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_48000) {
13628fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 48000;
13638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
136600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
1368db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg						rate_count, rate_list);
1369d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1370d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1371e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
13726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
13736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
13746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf,
1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				struct bluetooth_alsa_config *bt_config)
13776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
137892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_iterator_t i, next;
137992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
1381ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg
13829fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	/* Set defaults */
13839fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	bt_config->autoconnect = 1;
13849fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_for_each(i, next, conf) {
138692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		snd_config_t *n = snd_config_iterator_entry(i);
1387d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg		const char *id, *value;
138892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
138992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (snd_config_get_id(n, &id) < 0)
139092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
139192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
139292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
139392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
139492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
13959fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		if (strcmp(id, "autoconnect") == 0) {
1396a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			int b;
1397a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg
1398a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			b = snd_config_get_bool(n);
1399a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			if (b < 0) {
14009fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				SNDERR("Invalid type for %s", id);
14019fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				return -EINVAL;
14029fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			}
14039fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1404a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			bt_config->autoconnect = b;
14059fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			continue;
14069fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		}
14079fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1408b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
1409d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
141092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
141192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
141292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1413b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_device = 1;
1415d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			strncpy(bt_config->device, value, 18);
141692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
141792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
141892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1419b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "profile") == 0) {
1420d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
142192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
142292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
142392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1424b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1425d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (strcmp(value, "auto") == 0) {
1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1428d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "voice") == 0 ||
1429d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "hfp") == 0) {
1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1432d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "hifi") == 0 ||
1433d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "a2dp") == 0) {
1434d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1435d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
143792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
143892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
143992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "rate") == 0) {
1441d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14445402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14455402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1446d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->rate = atoi(value);
1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_rate = 1;
14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
145141b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz		if (strcmp(id, "mode") == 0) {
1452d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "mono") == 0) {
1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
1459d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1460d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "dual") == 0) {
1461d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
1462d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1463d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "stereo") == 0) {
1464d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
1465d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1466d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "joint") == 0) {
1467d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
1468d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1469d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "allocation") == 0) {
1474d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14755402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "loudness") == 0) {
1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
1481d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1482d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "snr") == 0) {
1483d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
1484d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1485d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14865402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "subbands") == 0) {
1490d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1495d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->subbands = atoi(value);
1496d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_subbands = 1;
14975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
15005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "blocks") == 0) {
1501d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
15025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
15035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
15045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
15055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1506d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->block_length = atoi(value);
1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_block_length = 1;
15085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
15095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
15105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
15115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "bitpool") == 0) {
1512d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
15135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
15145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
15155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
15165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1517d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->bitpool = atoi(value);
1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_bitpool = 1;
15195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
15205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
15215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
152292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		SNDERR("Unknown field %s", id);
152392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		return -EINVAL;
152492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	}
152592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
15265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return 0;
15275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
15285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1529d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
15305402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
15321c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
15331c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
15341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
15356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1536a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz	DBG("sending %s:%s", bt_audio_strtype(msg->type),
1537a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz		bt_audio_strname(msg->name));
15381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	if (send(sk, msg, length, 0) > 0)
1539d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = 0;
1540d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else {
1541d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error sending data to audio service: %s(%d)",
1543d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strerror(errno), errno);
15448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
1545b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1546d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1547d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
15486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1549d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
1550d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
15517c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	int err;
15527c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	ssize_t ret;
15531c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	const char *type, *name;
15541c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
15551c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
15561c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
1557d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1558d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("trying to receive msg from audio service...");
15592f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg
15602f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	ret = recv(sk, inmsg, length, 0);
15612f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	if (ret < 0) {
15622f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		err = -errno;
15632f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		SNDERR("Error receiving IPC data from bluetoothd: %s (%d)",
15642f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg						strerror(errno), errno);
15657c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
15662f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		SNDERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
15672f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg		err = -EINVAL;
15682f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg	} else {
15691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		type = bt_audio_strtype(inmsg->type);
15701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		name = bt_audio_strname(inmsg->name);
15711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		if (type && name) {
15721c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			DBG("Received %s - %s", type, name);
1573d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = 0;
1574d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		} else {
1575d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			SNDERR("Bogus message type %d - name %d"
15772f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg					" received from audio service",
15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					inmsg->type, inmsg->name);
1579d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
15802f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg
15816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
15828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1583d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1584d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
1585dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg
15861c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp,
1587a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann							int expected_name)
1588d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
15891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	bt_audio_error_t *error;
15901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int err = audioservice_recv(sk, rsp);
15911c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (err != 0)
15931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return err;
15941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->name != expected_name) {
15961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		err = -EINVAL;
15971c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("Bogus message %s received while %s was expected",
15981c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(rsp->name),
15991c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(expected_name));
16001c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16021c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->type == BT_ERROR) {
16031c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		error = (void *) rsp;
16041c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("%s failed : %s(%d)",
16051c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					bt_audio_strname(rsp->name),
16061c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					strerror(error->posix_errno),
16071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					error->posix_errno);
16081c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -error->posix_errno;
1609f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
16101c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1611d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
16128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
16138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
16141c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
16151c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					struct bt_get_capabilities_rsp *rsp)
16161c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{
16171c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int bytes_left = rsp->h.length - sizeof(*rsp);
16181c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	codec_capabilities_t *codec = (void *) rsp->data;
16191c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	data->transport = codec->transport;
16211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
16231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return 0;
16241c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16251c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	while (bytes_left > 0) {
1626379d756055f32d46fe7e09e1d89be1f780abb144Luiz Augusto von Dentz		if ((codec->type == BT_A2DP_SBC_SINK) &&
1627c5e75a5051967530f29f9fabfb8593ef2723d57eLuiz Augusto von Dentz				!(codec->lock & BT_WRITE_LOCK))
16281c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			break;
16291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		bytes_left -= codec->length;
16311c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		codec = (void *) codec + codec->length;
16321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
16331c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (bytes_left <= 0 ||
16351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			codec->length != sizeof(data->a2dp.sbc_capabilities))
16361c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -EINVAL;
16371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16381c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	memcpy(&data->a2dp.sbc_capabilities, codec, codec->length);
16391c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	return 0;
16411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz}
16421c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1643a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmannstatic int bluetooth_init(struct bluetooth_data *data,
1644a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann				snd_pcm_stream_t stream, snd_config_t *conf)
16458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
16466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
1647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
16481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
1649cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_req *req = (void *) buf;
1650cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_rsp *rsp = (void *) buf;
1651f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
165200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
165300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = bluetooth_parse_config(conf, alsa_conf);
1655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1658e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = -1;
1659dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg	data->stream.fd = -1;
166000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sk = bt_audio_service_open();
1662e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley	if (sk <= 0) {
1663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1665b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1666b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1667e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = sk;
1668e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.events = POLLIN;
1669b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1670892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[0] = -1;
1671892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[1] = -1;
1672892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (pipe(data->pipefd) < 0) {
1674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
1678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
1682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
16861c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
16871c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
16881c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_GET_CAPABILITIES;
16891c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
16901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16919fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	if (alsa_conf->autoconnect)
16921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->flags |= BT_FLAG_AUTOCONNECT;
16939bdf6ba0c50a3d5500e616b0f9d63a190692cc2cLuiz Augusto von Dentz	strncpy(req->destination, alsa_conf->device, 18);
1694d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (alsa_conf->has_transport)
16951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = alsa_conf->transport;
1696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
16971c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1698721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
16991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
1700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1701d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
17031c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = 0;
17041c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
17051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg					BT_GET_CAPABILITIES);
1706d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1707d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1708d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
17091c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	bluetooth_parse_capabilities(data, rsp);
1710892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1711d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
1712d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1713d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed:
17149d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg	if (sk >= 0)
17159d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg		bt_audio_service_close(sk);
1716d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
17178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
17188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1719ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth);
1720ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann
17218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
17228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1723f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
17248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
17258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
172600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
17278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
17288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1729d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg	data = malloc(sizeof(struct bluetooth_data));
173000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
173100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
173200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
173300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
173400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1735ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg	err = bluetooth_init(data, stream, conf);
17368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
17378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
17388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1739f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
1740f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
174100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
1742f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
1743b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1744d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
17456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
17466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
17476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
17486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
17496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
17506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
17516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
17526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1753f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
1754b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1755b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
1756b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
175833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_a2dp_hw_constraint(&data->io);
175933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	else
176033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_hsp_hw_constraint(&data->io);
176133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1762b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
1763f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
17648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
1765b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1766b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1767f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
1768b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1769b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
1770b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1771b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
177265aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg	if (data)
177365aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg		bluetooth_exit(data);
17745ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
1775b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
17765ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
17775ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
17785ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
1779