pcm_bluetooth.c revision 474420e554deeec2f7a6e2f4459c04cc90b038e8
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/*
2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
53ff24ea225437af91db69a069caa65b00ed642d9Marcel Holtmann *  Copyright (C) 2006-2007  Nokia Corporation
6e823c15e43a6f924779e466d434c51157002d9eeMarcel Holtmann *  Copyright (C) 2004-2008  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 */
99d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	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 */
102d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	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 */
134d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	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 */
138d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	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,
149d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				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 */
2278dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			if (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];
433cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
434cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
435721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	int err;
436721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					io->period_size, io->buffer_size);
439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
440450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
441450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.type = BT_REQUEST;
442450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
443450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length = sizeof(*req);
4441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
445450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	strncpy(req->device, data->alsa_config.device, 18);
446450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
447450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->codec.length = sizeof(pcm_capabilities_t);
448450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
449721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
450721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
451721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
452450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
453450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
454721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
455721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
456721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
457450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	rsp->h.length = sizeof(*rsp);
458450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
4591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
460721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
461721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
462721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
463450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	data->transport = rsp->transport;
464450e5656a8de08051f221d63e026c259151ef274Johan Hedberg	data->link_mtu = rsp->link_mtu;
465721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
466721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	return 0;
467721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz}
468721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
4692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
4702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
4712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (freq) {
472489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_16000:
473489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_32000:
4742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
475489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_44100:
4762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
4792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 31;
4802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
4812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
4822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
4832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
4842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
4852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
4862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
487489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	case BT_SBC_SAMPLING_FREQ_48000:
4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 29;
4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
4942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Invalid sampling freq %u", freq);
5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data,
5068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				snd_pcm_hw_params_t *params)
5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
5088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
5098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities;
5108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	unsigned int max_bitpool, min_bitpool, rate, channels;
5118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int dir;
5128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
5138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_rate(params, &rate, &dir);
5148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	snd_pcm_hw_params_get_channels(params, &channels);
5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (rate) {
5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 48000:
518489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 44100:
521489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 32000:
524489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 16000:
527489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5302934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Rate %d not supported", rate);
5312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5322934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5332934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5348fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
5358fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->channel_mode = cfg->channel_mode;
5368fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (channels == 2) {
5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	} else {
5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (!cap->channel_mode) {
5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported channel modes");
5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_block_length)
5548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->block_length = cfg->block_length;
5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported block lengths");
5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_subbands)
5698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->subbands = cfg->subbands;
5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->subbands & BT_A2DP_SUBBANDS_8)
5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_8;
5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_4;
5742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported subbands");
5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_allocation_method)
5808fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		cap->allocation_method = cfg->allocation_method;
5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5868fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_bitpool)
5878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = max_bitpool = cfg->bitpool;
5888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	else {
5898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
5908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		max_bitpool = MIN(default_bitpool(cap->frequency,
5918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->channel_mode),
5928fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					cap->max_bitpool);
5938fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	}
5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	return 0;
5992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
6002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
6018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp)
602afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
6038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
604afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
605d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_reinit(&a2dp->sbc, 0);
6072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else
6082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_init(&a2dp->sbc, 0);
609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc_initialized = 1;
6102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
611489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
61223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_16000;
613d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
614489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
61523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_32000;
616d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
617489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
61823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_44100;
619d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
620489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
62123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.frequency = SBC_FREQ_48000;
622d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
623d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
62423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_MONO;
625d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
62623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
62723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
62823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
62923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
63023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_STEREO;
63123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz
63223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
63323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.allocation = active_capabilities.allocation_method
63623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
63723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz				: SBC_AM_LOUDNESS;
638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
639d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.subbands) {
640d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_4:
64123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_4;
642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
643d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_8:
64423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.subbands = SBC_SB_8;
645d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
648d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.block_length) {
649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_4:
65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_4;
651d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
652d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_8:
65323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_8;
654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_12:
65623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_12;
657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_16:
65923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz		a2dp->sbc.blocks = SBC_BLK_16;
660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
6648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
6668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz}
6678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
6698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
6708fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{
6718fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
6728fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
6731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
674cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_req *req = (void *) buf;
675cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_set_configuration_rsp *rsp = (void *) buf;
6768fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	int err;
6778fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6788fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
6798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz					io->period_size, io->buffer_size);
6808fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6818fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	err = bluetooth_a2dp_init(data, params);
6828fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
6838fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
6848fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
6851c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
6861c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
6871c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_SET_CONFIGURATION;
6881c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
6891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
6901c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	strncpy(req->device, data->alsa_config.device, 18);
6911c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memcpy(&req->codec, &a2dp->sbc_capabilities,
6921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg			sizeof(a2dp->sbc_capabilities));
6931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
6941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
6951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->codec.length = sizeof(a2dp->sbc_capabilities);
6961c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
6978fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
6988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
6991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length += req->codec.length - sizeof(req->codec);
7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7011c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
7028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = sizeof(*rsp);
7061c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
7071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					BT_SET_CONFIGURATION);
7088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (err < 0)
7098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		return err;
7108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7111c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	data->transport = rsp->transport;
7121c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	data->link_mtu = rsp->link_mtu;
7138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
7148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	/* Setup SBC encoder now we agree on parameters */
7158fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	bluetooth_a2dp_setup(a2dp);
716d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
717d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
718d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
719d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.bitpool);
720d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
721d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
722afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
723afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
725f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann					struct pollfd *pfd, unsigned int space)
726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
727e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
728e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
729e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(io);
730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
734e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pfd[0].fd = data->stream.fd;
735e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
736e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
737e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
739e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
740e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
741e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
742e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg					struct pollfd *pfds, unsigned int nfds,
743dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
744e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
745e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds && nfds == 1 && revents);
746e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
747e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = pfds[0].revents;
748e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
749e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
750e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
751e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
75237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io)
75337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{
75437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
75537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz}
75637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
757892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
75838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfd, unsigned int space)
759e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
760e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
762e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
764892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	assert(data->pipefd[0] >= 0);
765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
76637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (space < 2)
767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
769892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	pfd[0].fd = data->pipefd[0];
770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
77237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].fd = data->stream.fd;
77337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].events = POLLERR | POLLHUP | POLLNVAL;
77437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	pfd[1].revents = 0;
775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
77637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	return 2;
777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
779892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
78038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfds, unsigned int nfds,
781dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
782e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	static char buf[1];
784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret;
785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds);
78937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(nfds == 2);
790e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(revents);
791e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds[0].fd >= 0);
79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	assert(pfds[1].fd >= 0);
793e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
794e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (io->state != SND_PCM_STATE_PREPARED)
795e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = read(pfds[0].fd, buf, 1);
796e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
79737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
79837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz		io->state = SND_PCM_STATE_DISCONNECTED;
79937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz
80037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	revents[0] = (pfds[0].revents & ~POLLIN) | POLLOUT;
80137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	revents[1] = (pfds[1].revents & ~POLLIN);
802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
803e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
805e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
806e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
8076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
80838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
809dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
810dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
81300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
81400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
815f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int nrecv, frame_size = 0;
8168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
81738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
81838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8203709666344736da68472f754ac52edc356039058Johan Hedberg	frame_size = areas->step / 8;
8213709666344736da68472f754ac52edc356039058Johan Hedberg
82200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
82300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
82400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
825d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
826474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg					io->nonblock ? MSG_DONTWAIT : 0);
82700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
82800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
82900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
83000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
83200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
833d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (nrecv != data->link_mtu) {
83400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
83500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
83600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
83900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
840d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
841721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz				io->buffer_size;
84200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
84300c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
8446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
84600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
847d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
84800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
84900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
850d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_write = (data->link_mtu - data->count) / frame_size;
85100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
852f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
853f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
854d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->count %= data->link_mtu;
85500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
85600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
85700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
85800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
85900c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
86000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
8618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
8628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
8638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
86538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
866dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
867dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
8718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
872c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
873f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
8748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
87538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
87638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
878892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (io->hw_ptr > io->appl_ptr) {
879892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
880892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (ret == 0)
881892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz			ret = -EPIPE;
882892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		goto done;
883892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
884892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
885f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
886d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
8878742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
8888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
889d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_read = (data->link_mtu - data->count) / frame_size;
8908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
89138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
892c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
8938742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
8946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
896f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
8978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
8992a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
900d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->count != data->link_mtu) {
9018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
90200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
9038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
9048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
905d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
906c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
90700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
90800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
90900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
91000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
91100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
91200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
91300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
91400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
91500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
91600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
91700c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	DBG("returning %ld", ret);
9196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
92338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
924dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
925dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
931e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data)
9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
933e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret = 0;
9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
9369494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
9426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
9446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
9456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
9466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
9476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
9486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
9496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
950bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
951dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret < 0) {
952dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("send returned %d errno %s.", ret, strerror(errno));
953e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = -errno;
954dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
9558905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg
9566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
9606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
9616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
962f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg	return ret;
9636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
96638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
96738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
972bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	int frame_size, encoded, written, bytes_left;
9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
9746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
97538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
97638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				areas->step, areas->first, offset, size);
977dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
978dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			io->appl_ptr - io->hw_ptr);
979e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
980bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Calutate starting pointers */
981bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	frame_size = areas->step / 8;
982bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	bytes_left = size * frame_size;
983bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	buff = (uint8_t *) areas->addr +
984bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann				(areas->first + areas->step * (offset)) / 8;
985bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
986bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check for underrun */
987cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->hw_ptr > io->appl_ptr) {
988892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
989de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		if (ret == 0)
990e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			ret = -EPIPE;
991dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->reset = 1;
992bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		return ret;
993de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz	}
994e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
995e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	/* Check if we should autostart */
996cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->state == SND_PCM_STATE_PREPARED) {
997e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_t *swparams;
998e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_uframes_t threshold;
999de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
1000e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_malloc(&swparams);
100138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
1002dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				!snd_pcm_sw_params_get_start_threshold(swparams,
1003dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg								&threshold)) {
1004cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg			if (io->appl_ptr >= threshold) {
1005e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg				ret = snd_pcm_start(io->pcm);
1006cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg				if (ret != 0)
1007bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					return ret;
1008e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			}
1009e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		}
1010dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1011de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		snd_pcm_sw_params_free(swparams);
1012e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
10136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1014bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Check if we have any left over data from the last write */
1015bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	if (data->count > 0 && (bytes_left - data->count) >= a2dp->codesize) {
1016bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		int additional_bytes_needed = a2dp->codesize - data->count;
10176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1018dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		memcpy(data->buffer + data->count, buff,
1019bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						additional_bytes_needed);
10206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1021dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Enough data to encode (sbc wants 1k blocks) */
1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize,
1023fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					a2dp->buffer + a2dp->count,
1024fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					sizeof(a2dp->buffer) - a2dp->count,
1025bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1026dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (encoded <= 0) {
1027dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Encoding error %d", encoded);
1028dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1029dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1031bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1032397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->count += written;
1033397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->frame_count++;
1034397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->samples += encoded / frame_size;
1035397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->nsamples += encoded / frame_size;
10366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1037397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		/* No space left for another frame then send */
1038d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (a2dp->count + written >= data->link_mtu) {
1039dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			avdtp_write(data);
1040d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("sending packet %d, count %d, link_mtu %u",
1041d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					a2dp->seq_num, a2dp->count,
1042bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1043bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1044bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1045bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1046bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1047bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += additional_bytes_needed;
1048bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= additional_bytes_needed;
1049bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1050bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Since data has been process mark it as zero */
1051bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count = 0;
1052bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
1053bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1055bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Process this buffer in full chunks */
1056bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	while (bytes_left >= a2dp->codesize) {
1057bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Enough data to encode (sbc wants 1k blocks) */
1058bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize,
1059bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					a2dp->buffer + a2dp->count,
1060bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann					sizeof(a2dp->buffer) - a2dp->count,
1061bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann								&written);
1062bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (encoded <= 0) {
1063bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			DBG("Encoding error %d", encoded);
1064bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			goto done;
1065f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg		}
10666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1067bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment up buff pointer to take into account
1068bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		 * the data processed */
1069bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		buff += a2dp->codesize;
1070bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left -= a2dp->codesize;
1071bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1072bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* Increment a2dp buffers */
1073bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->count += written;
1074bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->frame_count++;
1075bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->samples += encoded / frame_size;
1076bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		a2dp->nsamples += encoded / frame_size;
1077bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1078bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		/* No space left for another frame then send */
1079bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		if (a2dp->count + written >= data->link_mtu) {
1080bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann			avdtp_write(data);
10818a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg			DBG("sending packet %d, count %d, link_mtu %u",
1082bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann						a2dp->seq_num, a2dp->count,
1083bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann							data->link_mtu);
1084bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		}
1085dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
1086dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	/* Copy the extra to our temp buffer for the next write */
1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	if (bytes_left > 0) {
1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		memcpy(data->buffer + data->count, buff, bytes_left);
1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		data->count += bytes_left;
1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann		bytes_left = 0;
1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	}
10936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	DBG("returning %ld", size - bytes_left / frame_size);
1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann
1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann	return size - bytes_left / frame_size;
10988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
10998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
11006967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
11016967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg					snd_pcm_sframes_t *delayp)
1102a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{
1103a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	DBG("");
1104a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
1105a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This updates io->hw_ptr value using pointer() function */
1106a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	snd_pcm_hwsync(io->pcm);
11076967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1108a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	*delayp = io->appl_ptr - io->hw_ptr;
1109a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
1110a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->callback->stop(io);
1111a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->state = SND_PCM_STATE_XRUN;
1112a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		*delayp = 0;
1113a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	}
11146967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1115a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This should never fail, ALSA API is really not
1116a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	prepared to handle a non zero return value */
1117a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	return 0;
1118a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley}
1119a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
11206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
1121892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1122892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1123e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1124e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1125721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1126e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1127e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_write,
112837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1129892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1130892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1131a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
1135e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1136e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1137e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1138e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1139721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1140e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1141e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_read,
1142e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1143e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
11466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
1147892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1148892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1149e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1150e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1151e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1152e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1153e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_write,
115437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz	.poll_descriptors_count	= bluetooth_playback_poll_descriptors_count,
1155892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1156892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
1161e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1162e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1163e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_read,
1168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1169e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1170b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1171b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1172b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
1173b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
117433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
1175b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1176c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1177b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
1178b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
1179b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
1180b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
1181b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
1182b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
1183b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1184b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
1185b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_FORMAT_S16_LE
1186b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1187d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1188b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1189c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
1190b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1191b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
1192b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1193b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1194b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1195c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
1196b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1197b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
1198b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1199b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1200b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1201c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
1202c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1203d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							1, 1);
1204b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1205b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1206b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
120735b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
1208c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1209d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							8000, 8000);
1210b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1211b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1212b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
121335b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
1214c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1215d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						data->link_mtu, data->link_mtu);
1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1218b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1219c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1220f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann									2, 200);
122133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
122233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
122333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
122433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	return 0;
122533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz}
122633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
122733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
122833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{
122933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1230d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
12318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	struct bluetooth_alsa_config *cfg = &data->alsa_config;
123233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	snd_pcm_access_t access_list[] = {
123333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_RW_INTERLEAVED,
123433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		/* Mmap access is really useless fo this driver, but we
123533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * support it because some pieces of software out there
123633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * insist on using it */
123733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_MMAP_INTERLEAVED
123833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
123933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	unsigned int format_list[] = {
124033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_FORMAT_S16_LE
124133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
1242d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_list[4];
1243d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_count;
1244d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err, min_channels, max_channels;
1245dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	unsigned int period_list[] = {
1246db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		2048,
1247db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
1248db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		8192
1249dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	};
125033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
125133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* access type */
125233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
125333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(access_list), access_list);
125433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
125533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
125633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
125733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported formats */
125833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
125933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(format_list), format_list);
126033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
126133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
126233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
126333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported channels */
12648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_channel_mode)
12658fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		a2dp->sbc_capabilities.channel_mode = cfg->channel_mode;
12668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz
12678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode &
12688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			BT_A2DP_CHANNEL_MODE_MONO)
1269d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 1;
1270d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1271d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 2;
127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
12738fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode &
12748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			(~BT_A2DP_CHANNEL_MODE_MONO))
1275d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 2;
1276d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1277d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 1;
1278d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1279d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1280d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							min_channels, max_channels);
128133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
128233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
128333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1284db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported buffer sizes
1285db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
1286cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	err = snd_pcm_ioplug_set_param_minmax(io,
1287cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1288cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg						8192*3, 8192*3);
128983a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg	if (err < 0)
129083a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg		return err;
129183a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg
1292db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported block sizes: */
1293db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1294db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg				ARRAY_NELEMS(period_list), period_list);
1295b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1296b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1297b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* supported rates */
1299d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rate_count = 0;
13008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	if (cfg->has_rate) {
13018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		rate_list[rate_count] = cfg->rate;
1302d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
13038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz	} else {
13048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_16000) {
13068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 16000;
13078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1309ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
13108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_32000) {
13128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 32000;
13138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1315ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
13168fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13178fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_44100) {
13188fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 44100;
13198fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13208fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
132100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
13228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		if (a2dp->sbc_capabilities.frequency &
13238fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz				BT_SBC_SAMPLING_FREQ_48000) {
13248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_list[rate_count] = 48000;
13258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			rate_count++;
13268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz		}
1327d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
132800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1329d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
1330db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg						rate_count, rate_list);
1331d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1332d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1333e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
13346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
13356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
13366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf,
1338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				struct bluetooth_alsa_config *bt_config)
13396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
134092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_iterator_t i, next;
134192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
1343ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg
13449fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	/* Set defaults */
13459fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	bt_config->autoconnect = 1;
13469fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
134792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_for_each(i, next, conf) {
134892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		snd_config_t *n = snd_config_iterator_entry(i);
1349d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg		const char *id, *value;
135092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
135192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (snd_config_get_id(n, &id) < 0)
135292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
135392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
135492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
135592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
135692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
13579fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		if (strcmp(id, "autoconnect") == 0) {
1358a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			int b;
1359a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg
1360a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			b = snd_config_get_bool(n);
1361a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			if (b < 0) {
13629fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				SNDERR("Invalid type for %s", id);
13639fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				return -EINVAL;
13649fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			}
13659fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1366a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg			bt_config->autoconnect = b;
13679fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			continue;
13689fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		}
13699fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1370b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
1371d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
137292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
137392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
137492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1375b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_device = 1;
1377d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			strncpy(bt_config->device, value, 18);
137892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
137992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
138092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1381b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "profile") == 0) {
1382d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
138392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
138492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1386b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1387d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (strcmp(value, "auto") == 0) {
1388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1390d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "voice") == 0 ||
1391d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "hfp") == 0) {
1392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1394d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "hifi") == 0 ||
1395d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg						strcmp(value, "a2dp") == 0) {
1396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
139992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
140092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
140192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "rate") == 0) {
1403d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1408d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->rate = atoi(value);
1409d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_rate = 1;
14105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14125402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
141341b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz		if (strcmp(id, "mode") == 0) {
1414d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14198fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "mono") == 0) {
1420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
1421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1422d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "dual") == 0) {
1423d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
1424d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1425d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "stereo") == 0) {
1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1428d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "joint") == 0) {
1429d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "allocation") == 0) {
1436d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14385402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14395402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz			if (strcmp(value, "loudness") == 0) {
1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
1443d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1444d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			} else if (strcmp(value, "snr") == 0) {
1445d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
1446d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "subbands") == 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
1457d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->subbands = atoi(value);
1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_subbands = 1;
14595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "blocks") == 0) {
1463d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			if (snd_config_get_string(n, &value) < 0) {
14645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1468d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->block_length = atoi(value);
1469d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_block_length = 1;
14705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "bitpool") == 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
1479d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg			bt_config->bitpool = atoi(value);
1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_bitpool = 1;
14815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
148492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		SNDERR("Unknown field %s", id);
148592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		return -EINVAL;
148692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	}
148792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return 0;
14895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
14905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1491d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1493d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
14941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
14951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
14961c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
14976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1498d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("sending %s", bt_audio_strmsg(msg->msg_type));
14991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	if (send(sk, msg, length, 0) > 0)
1500d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = 0;
1501d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else {
1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1503d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error sending data to audio service: %s(%d)",
1504d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strerror(errno), errno);
15058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
1506b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1508d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
15096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1510d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
1511d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
1512d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
15131c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	const char *type, *name;
15141c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	uint16_t length;
15151c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg
15161c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
1517d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("trying to receive msg from audio service...");
15191c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	if (recv(sk, inmsg, length, 0) > 0) {
15201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		type = bt_audio_strtype(inmsg->type);
15211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		name = bt_audio_strname(inmsg->name);
15221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		if (type && name) {
15231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			DBG("Received %s - %s", type, name);
1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = 0;
1525d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		} else {
1526d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
15271c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			SNDERR("Bogus message type %d - name %d"
1528d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					"received from audio service",
15291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					inmsg->type, inmsg->name);
1530d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
1532d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1533d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error receiving data from audio service: %s(%d)",
1534d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					strerror(errno), errno);
15356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
15368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1537d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1538d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
1539dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg
15401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp,
15411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				int expected_name)
1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
15431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	bt_audio_error_t *error;
15441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int err = audioservice_recv(sk, rsp);
15451c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (err != 0)
15471c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return err;
15481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15491c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->name != expected_name) {
15501c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		err = -EINVAL;
15511c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("Bogus message %s received while %s was expected",
15521c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(rsp->name),
15531c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz				bt_audio_strname(expected_name));
15541c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
15551c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15561c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (rsp->type == BT_ERROR) {
15571c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		error = (void *) rsp;
15581c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		SNDERR("%s failed : %s(%d)",
15591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					bt_audio_strname(rsp->name),
15601c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					strerror(error->posix_errno),
15611c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					error->posix_errno);
15621c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -error->posix_errno;
1563f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
15641c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1565d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
15668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
15678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
15681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
15691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz					struct bt_get_capabilities_rsp *rsp)
15701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{
15711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	int bytes_left = rsp->h.length - sizeof(*rsp);
15721c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	codec_capabilities_t *codec = (void *) rsp->data;
15731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15741c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	data->transport = codec->transport;
15751c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
15771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return 0;
15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15791c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	while (bytes_left > 0) {
15801c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		if (codec->type == BT_A2DP_CODEC_SBC)
15811c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			break;
15821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15831c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		bytes_left -= codec->length;
15841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		codec = (void *) codec + codec->length;
15851c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	}
15861c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15871c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	if (bytes_left <= 0 ||
15881c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz			codec->length != sizeof(data->a2dp.sbc_capabilities))
15891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz		return -EINVAL;
15901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15911c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	memcpy(&data->a2dp.sbc_capabilities, codec, codec->length);
15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
15931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	return 0;
15941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz}
15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
1596ec384afacde8614306abe32cf40c55b795783f0eJohan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,
1597ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg				snd_config_t *conf)
15988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
15996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
1600d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz	char buf[BT_SUGGESTED_BUFFER_SIZE];
1602cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_req *req = (void *) buf;
1603cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg	struct bt_get_capabilities_rsp *rsp = (void *) buf;
1604f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
160500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
160600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1607d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = bluetooth_parse_config(conf, alsa_conf);
1608d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1610d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1611e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = -1;
1612dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg	data->stream.fd = -1;
161300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1614d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sk = bt_audio_service_open();
1615e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley	if (sk <= 0) {
1616d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1617d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1618b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1619b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1620e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = sk;
1621e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.events = POLLIN;
1622b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1623892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[0] = -1;
1624892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[1] = -1;
1625892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1626d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (pipe(data->pipefd) < 0) {
1627d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1629d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1630d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
1631d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1633d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
1635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1636d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
16391c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
16401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.type = BT_REQUEST;
16411c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.name = BT_GET_CAPABILITIES;
16421c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	req->h.length = sizeof(*req);
16431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz
16449fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	if (alsa_conf->autoconnect)
16451c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->flags |= BT_FLAG_AUTOCONNECT;
16461c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	strncpy(req->device, alsa_conf->device, 18);
1647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (alsa_conf->has_transport)
16481c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = alsa_conf->transport;
1649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
16501c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg		req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1651721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
16521c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_send(data->server.fd, &req->h);
1653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
16561c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	rsp->h.length = 0;
16571c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	err = audioservice_expect(data->server.fd, &rsp->h,
16581c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg					BT_GET_CAPABILITIES);
1659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
16621c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg	bluetooth_parse_capabilities(data, rsp);
1663892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
1665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed:
1667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	bt_audio_service_close(sk);
1668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
16698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
16708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1671ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth);
1672ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann
16738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
16748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1675f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
16768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
16778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
167800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
16798742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
16808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1681d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg	data = malloc(sizeof(struct bluetooth_data));
168200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
168300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
168400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
168500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
168600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1687ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg	err = bluetooth_init(data, stream, conf);
16888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
16898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
16908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1691f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
1692f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
169300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
1694f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
1695b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
16976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
16986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
16996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
17006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
17016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
17026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
17036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
17046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1705f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
1706b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1707b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
1708b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1709d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
171033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_a2dp_hw_constraint(&data->io);
171133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	else
171233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_hsp_hw_constraint(&data->io);
171333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1714b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
1715f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
17168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
1717b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1718b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1719f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
1720b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1721b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
1722b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1723b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
17245ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
17255ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
1726b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
17275ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
17285ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
17295ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
1730