pcm_bluetooth.c revision 9fa2613525721908ec43189794fe99828b8a4f51
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/*
2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
53ff24ea225437af91db69a069caa65b00ed642d9Marcel Holtmann *  Copyright (C) 2006-2007  Nokia Corporation
6e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Copyright (C) 2004-2007  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>
366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h>
38b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
395ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h>
405ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h>
415ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
42b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h"
436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h"
44347675ea994642c0ccd60f7af70f369f7a2d7a88Luiz Augusto von Dentz#include "rtp.h"
456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann//#define ENABLE_DEBUG
476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
48714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#define UINT_SECS_MAX (UINT_MAX / 1000000 - 1)
49714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg
50e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz#define MIN_PERIOD_TIME 1
51714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg
52f5befe8ab54b797a0a5357ceddf2f05ab0ff163cJohan Hedberg#define BUFFER_SIZE 2048
53b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
54f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG
55b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
56f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else
57f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...)
58f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif
59b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
6097c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#ifndef SOL_SCO
6197c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#define SOL_SCO 17
6297c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#endif
6397c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann
648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS
658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03
668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS
698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04
708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MIN
732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MIN(x, y) ((x) < (y) ? (x) : (y))
742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif
752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MAX
772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MAX(x, y) ((x) > (y) ? (x) : (y))
782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif
792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MAX_BITPOOL 64
812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MIN_BITPOOL 2
822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
83d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg/* adapted from glibc sys/time.h timersub() macro */
84d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg#define priv_timespecsub(a, b, result)					\
85d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	do {								\
86d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;		\
87d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;	\
88d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		if ((result)->tv_nsec < 0) {				\
89d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			--(result)->tv_sec;				\
90d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			(result)->tv_nsec += 1000000000;		\
91d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		}							\
92d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	} while (0)
93344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg
946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp {
95d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_capabilities_t sbc_capabilities;
96d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_t sbc;				/* Codec data */
97d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int sbc_initialized;			/* Keep track if the encoder is initialized */
98d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int codesize;				/* SBC codesize */
99d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int samples;				/* Number of encoded samples */
100d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
101d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int count;				/* Codec transfer buffer counter */
102d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
103d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int nsamples;				/* Cumulative number of codec samples */
104d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint16_t seq_num;			/* Cumulative packet sequence */
105d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int frame_count;			/* Current frames in buffer*/
106d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz};
107d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
108d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstruct bluetooth_alsa_config {
109d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char device[18];		/* Address of the remote Device */
110d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_device;
111d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t transport;		/* Requested transport */
112d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_transport;
113d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint16_t rate;
114d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_rate;
115d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t channel_mode;		/* A2DP only */
116d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_channel_mode;
117d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t allocation_method;	/* A2DP only */
118d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_allocation_method;
119d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t subbands;		/* A2DP only */
120d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_subbands;
121d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t block_length;		/* A2DP only */
122d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_block_length;
123d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t bitpool;		/* A2DP only */
124d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int has_bitpool;
1259fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	int autoconnect;
1266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
1276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data {
129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_ioplug_t io;
130d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config alsa_config;	/* ALSA resource file parameters */
131e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	volatile snd_pcm_sframes_t hw_ptr;
132d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int transport;					/* chosen transport SCO or AD2P */
133d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int link_mtu;					/* MTU for selected transport channel */
134d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	volatile struct pollfd stream;			/* Audio stream filedescriptor */
135d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct pollfd server;				/* Audio daemon filedescriptor */
136d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t buffer[BUFFER_SIZE];		/* Encoded transfer buffer */
137d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int count;					/* Transfer buffer counter */
138d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp a2dp;			/* A2DP data */
139d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
140d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	pthread_t hw_thread;				/* Makes virtual hw pointer move */
141d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int pipefd[2];					/* Inter thread communication */
142892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	int stopped;
143dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	sig_atomic_t reset;             /* Request XRUN handling */
144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
146d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg);
147d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg,
148d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				int expected_type);
149d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
150b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io)
151b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1529217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_start %p", io);
153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
156b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io)
158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1599217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_stop %p", io);
160b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
163b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
164892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic void *playback_hw_thread(void *param)
165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = param;
167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	unsigned int prev_periods;
168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	double period_time;
169d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	struct timespec start;
170e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	struct pollfd fds[2];
1713e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	int poll_timeout;
172e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
173dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->server.events = POLLIN;
174dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	/* note: only errors for data->stream.events */
175dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
176e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[0] = data->server;
177e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[1] = data->stream;
178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	prev_periods = 0;
180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	period_time = 1000000.0 * data->io.period_size / data->io.rate;
1813e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	if (period_time > (int) (MIN_PERIOD_TIME * 1000))
1823e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = (int) (period_time / 1000.0f);
1833e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	else
1843e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = MIN_PERIOD_TIME;
185e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
186d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	clock_gettime(CLOCK_MONOTONIC, &start);
187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	while (1) {
189714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg		unsigned int dtime, periods;
190d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		struct timespec cur, delta;
191e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		int ret;
192e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
193892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (data->stopped)
194f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg			goto iter_sleep;
195f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
196dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (data->reset) {
197dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Handle XRUN in hw-thread.");
198dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->reset = 0;
199d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			clock_gettime(CLOCK_MONOTONIC, &start);
200dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			prev_periods = 0;
201dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
202dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
203d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		clock_gettime(CLOCK_MONOTONIC, &cur);
204e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
205d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		priv_timespecsub(&cur, &start, &delta);
206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
207d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000;
208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		periods = 1.0 * dtime / period_time;
209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		if (periods > prev_periods) {
211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			char c = 'w';
212dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			int frags = periods - prev_periods, n;
213e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
214dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->hw_ptr += frags *	data->io.period_size;
215e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			data->hw_ptr %= data->io.buffer_size;
216e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
217dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			for (n = 0; n < frags; n++) {
218dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				/* Notify user that hardware pointer
219dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				 * has moved * */
220dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				if (write(data->pipefd[1], &c, 1) < 0)
221dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					pthread_testcancel();
222dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			}
223e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
224714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			/* Reset point of reference to avoid too big values
225714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			 * that wont fit an unsigned int */
2268dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			if (delta.tv_sec < UINT_SECS_MAX)
2278dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg				prev_periods = periods;
2288dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			else {
229714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg				prev_periods = 0;
230d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg				clock_gettime(CLOCK_MONOTONIC, &start);
2318dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			}
232de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		}
233e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
234f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedbergiter_sleep:
2353e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		/* sleep up to one period interval */
2363e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		ret = poll(fds, 2, poll_timeout);
237dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
238e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		if (ret < 0) {
239e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll error: %s (%d)", strerror(errno), errno);
240e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			if (errno != EINTR)
241e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
242e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		} else if (ret > 0) {
243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			ret = (fds[0].revents) ? 0 : 1;
244e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll fd %d revents %d", ret, fds[ret].revents);
245db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann			if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL))
246e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
247e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		}
248e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
249e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		/* Offer opportunity to be canceled by main thread */
250de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		pthread_testcancel();
251e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
252e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
253e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->hw_thread = 0;
254e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pthread_exit(NULL);
255e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
25633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
257892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io)
258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
259e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
260e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int err;
261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
263e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
264892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 0;
265f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
266892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread)
267f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		return 0;
268e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
269892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
270e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return -err;
272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
273e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
274892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
275e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
277e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
279e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
280892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 1;
281e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
2827090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg	return 0;
283e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
284e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
285b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return data->hw_ptr;
290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
2925ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data)
2935ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{
294892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
295892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
296e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->server.fd >= 0)
297d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		bt_audio_service_close(data->server.fd);
2985ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
299e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->stream.fd >= 0)
300e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		close(data->stream.fd);
3012a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz
302892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread) {
303892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
304892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
305892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
306f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
308f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		sbc_finish(&a2dp->sbc);
309d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz
310892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[0] > 0)
311892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[0]);
312de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
313892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[1] > 0)
314892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[1]);
315de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
3165ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	free(data);
3175ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz}
3185ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
319b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io)
320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
321b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
322b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("%p", io);
324b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3255ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
326b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
328b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
329b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io)
3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
3328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
333e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	char c = 'w';
334d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
335d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_streamstart_req *start_req = (void*) buf;
336d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
337d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	struct bt_streamfd_ind *streamfd_ind = (void*) buf;
338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int opt_name, err;
340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct timeval t = { 0, period_count };
3418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
34238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
34338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					io->period_size, io->buffer_size);
3448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
345dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->reset = 0;
346dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
347d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* As we're gonna receive messages on the server socket, we have to stop the
348d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	   hw thread that is polling on it, if any */
349d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->hw_thread) {
350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->hw_thread = 0;
353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3559217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	if (io->stream == SND_PCM_STREAM_PLAYBACK)
35600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* If not null for playback, xmms doesn't display time
35700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * correctly */
3588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = 0;
3599217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	else
36000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* ALSA library is really picky on the fact hw_ptr is not null.
36100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * If it is, capture won't start */
3628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = io->period_size;
3639217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* send start */
365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
366d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	start_req->h.msg_type = BT_STREAMSTART_REQ;
3678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
368d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &start_req->h);
369d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
370d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
371d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
372d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_STREAMSTART_RSP);
374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
377d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
378d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_START failed : %s(%d)",
379d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
380d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
381d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
383d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
384d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &streamfd_ind->h,
385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_STREAMFD_IND);
386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd >= 0)
390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		close(data->stream.fd);
391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd < 0) {
394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return -errno;
395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
3969217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
399d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						SO_SNDTIMEO : SO_RCVTIMEO;
400ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							sizeof(t)) < 0)
403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return -errno;
404d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
405d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
40638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SCO_TXBUFS : SCO_RXBUFS;
4078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
40938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4119217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
412d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
41338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SO_SNDBUF : SO_RCVBUF;
41400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
41638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4187090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg
419d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		/* FIXME : handle error codes */
420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
42100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* wake up any client polling at us */
423d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return write(data->pipefd[1], &c, 1);
4248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
4258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
426721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
427721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
428721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{
429721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
432721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bt_setconfiguration_req *setconf_req = (void*) buf;
433721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
434721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	int err;
435721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
436721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					io->period_size, io->buffer_size);
438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	strncpy(setconf_req->device, data->alsa_config.device, 18);
442721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_SCO;
443721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
444721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
445721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
446721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
447721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &setconf_req->h);
448721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
449721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
450721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
451721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
452721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					BT_SETCONFIGURATION_RSP);
453721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
454721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
455721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
456721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
457721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		SNDERR("BT_SETCONFIGURATION failed : %s(%d)",
458721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
459721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					rsp_hdr->posix_errno);
460721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return -rsp_hdr->posix_errno;
461721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	}
462721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
463721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	data->transport = setconf_rsp->transport;
464721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	data->link_mtu = setconf_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
5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic int select_sbc_params(sbc_capabilities_t *cap, unsigned int rate,
5062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz				unsigned int channels)
5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
5082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	unsigned int max_bitpool, min_bitpool;
5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (rate) {
5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 48000:
512489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 44100:
515489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 32000:
518489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 16000:
521489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5242934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Rate %d not supported", rate);
5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (channels == 2) {
5292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
5302934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
5312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
5322934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
5332934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
5342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
5352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	} else {
5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (!cap->channel_mode) {
5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported channel modes");
5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
5532934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5542934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported block lengths");
5552934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->subbands & BT_A2DP_SUBBANDS_8)
5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_8;
5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_4;
5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported subbands");
5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
5742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz							cap->max_bitpool);
5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	return 0;
5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
583afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
584afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
585afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
586afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
587d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
588d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
589d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
590d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_setconfiguration_req *setconf_req = (void*) buf;
591d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	unsigned int rate, channels;
5932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	int err, dir;
594d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_capabilities_t active_capabilities;
595afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
596d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
597d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					io->period_size, io->buffer_size);
598afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
599d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* FIXME: this needs to be really implemented (take into account
600d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	real asoundrc settings + ALSA hw settings ) once server side sends us
601d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	more than one possible configuration */
6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	snd_pcm_hw_params_get_rate(params, &rate, &dir);
6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	snd_pcm_hw_params_get_channels(params, &channels);
6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	err = select_sbc_params(&a2dp->sbc_capabilities, rate, channels);
6052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (err < 0)
6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return err;
6072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
608d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	active_capabilities = a2dp->sbc_capabilities;
609afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
610d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
611d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
612721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	strncpy(setconf_req->device, data->alsa_config.device, 18);
613721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
614d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	setconf_req->sbc_capabilities = active_capabilities;
6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
6172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
618afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
619d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &setconf_req->h);
620d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
621d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
622e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
623d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
624d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_SETCONFIGURATION_RSP);
625d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
626d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
627afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
628d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
629d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_SETCONFIGURATION failed : %s(%d)",
630d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
631d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
632d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
633d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
6352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	data->transport = setconf_rsp->transport;
6362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	data->link_mtu = setconf_rsp->link_mtu;
6372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* Setup SBC encoder now we agree on parameters */
639d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
6402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_reinit(&a2dp->sbc, 0);
6412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else
6422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_init(&a2dp->sbc, 0);
643d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc_initialized = 1;
6442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
645489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 16000;
647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
648489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 32000;
650d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
651489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
652d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 44100;
653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
654489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 48000;
656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.channels = 1;
659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.channels = 2;
661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode &
663489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			(BT_A2DP_CHANNEL_MODE_MONO ||
664489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.joint = 1;
666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.joint = 0;
668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.allocation = active_capabilities.allocation_method
670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					== BT_A2DP_ALLOCATION_SNR ? 0x01 : 0x00;
671d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
672d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.subbands) {
673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_4:
674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.subbands = 4;
675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_8:
677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.subbands = 8;
678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.block_length) {
682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_4:
683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 4;
684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_8:
686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 8;
687d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
688d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_12:
689d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 12;
690d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
691d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_16:
692d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 16;
693d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
694d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
695d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
697d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->codesize = a2dp->sbc.subbands * a2dp->sbc.blocks *
698d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						a2dp->sbc.channels * 2;
699d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
701d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
703d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.bitpool);
704d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
705d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
706afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
707afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
708e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
709f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann					struct pollfd *pfd, unsigned int space)
710e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
711e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
712e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
713e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(io);
714e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
715e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
716e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
717e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
718e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pfd[0].fd = data->stream.fd;
719e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
720e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
721e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
722e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
723e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
725e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg					struct pollfd *pfds, unsigned int nfds,
727dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
728e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
729e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds && nfds == 1 && revents);
730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = pfds[0].revents;
732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
734e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
735e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
736892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
73738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfd, unsigned int space)
738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
739e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
740e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
741e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
742e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
743892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	assert(data->pipefd[0] >= 0);
744e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
745e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
746e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
747e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
748892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	pfd[0].fd = data->pipefd[0];
749e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
750e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
751e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
752e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
753e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
754e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
755892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
75638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfds, unsigned int nfds,
757dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
758e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
759e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	static char buf[1];
760e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret;
761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
762e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
764e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds);
765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(nfds == 1);
766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(revents);
767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds[0].fd >= 0);
768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (io->state != SND_PCM_STATE_PREPARED)
770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = read(pfds[0].fd, buf, 1);
771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = (pfds[0].revents & ~POLLIN) | POLLOUT;
773e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
776e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
7786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
77938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
780dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
781dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
7828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
7838742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
78400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
78500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
786f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int nrecv, frame_size = 0;
7878742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
78838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
78938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
7908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
7913709666344736da68472f754ac52edc356039058Johan Hedberg	frame_size = areas->step / 8;
7923709666344736da68472f754ac52edc356039058Johan Hedberg
79300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
79400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
79500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
796d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
79700c71248e732de0230c12df4240087a6b2747179Johan Hedberg			MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0));
79800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
79900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
80000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
80100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
80300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
804d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (nrecv != data->link_mtu) {
80500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
80600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
80700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
81000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
811d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
812721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz				io->buffer_size;
81300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
81400c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
8156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
8166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
81700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
818d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
81900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
82000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
821d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_write = (data->link_mtu - data->count) / frame_size;
82200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
823f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
824f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
825d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->count %= data->link_mtu;
82600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
82700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
82800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
82900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
83000c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
83100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
8328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
8338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
8348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
83638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
837dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
838dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
8418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
8428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
843c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
844f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
8458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
84638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
84738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
849892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (io->hw_ptr > io->appl_ptr) {
850892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
851892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (ret == 0)
852892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz			ret = -EPIPE;
853892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		goto done;
854892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
855892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
856f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
857d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
8588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
8598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
860d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_read = (data->link_mtu - data->count) / frame_size;
8618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
86238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
863c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
8648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
8656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
8666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
867f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
8702a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
871d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->count != data->link_mtu) {
8728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
876d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
877c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
87800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
87900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
88000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
88300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
88400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
88600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
88700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88800c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
889892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	DBG("returning %ld", ret);
8906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
8916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
89438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
895dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
896dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
8996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
9006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
902e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data)
9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
904e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret = 0;
9056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
9066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
9079494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
9106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
9116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
9136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
9156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
9166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
9176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
9186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
9196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
9206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
921dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg        ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
922dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret < 0) {
923dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("send returned %d errno %s.", ret, strerror(errno));
924e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = -errno;
925dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
9268905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg
9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
9316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
933f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg	return ret;
9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
93738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
93838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
9416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
943dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	snd_pcm_uframes_t frames_to_read, frames_left = size;
944397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz	int frame_size, encoded, written;
9456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
9466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
94738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
94838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				areas->step, areas->first, offset, size);
949dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
950dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			io->appl_ptr - io->hw_ptr);
951e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
952cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->hw_ptr > io->appl_ptr) {
953892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
954de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		if (ret == 0)
955e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			ret = -EPIPE;
956dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->reset = 1;
957de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		goto done;
958de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz	}
959e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
960e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	/* Check if we should autostart */
961cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->state == SND_PCM_STATE_PREPARED) {
962e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_t *swparams;
963e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_uframes_t threshold;
964de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
965e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_malloc(&swparams);
96638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
967dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				!snd_pcm_sw_params_get_start_threshold(swparams,
968dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg								&threshold)) {
969cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg			if (io->appl_ptr >= threshold) {
970e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg				ret = snd_pcm_start(io->pcm);
971cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg				if (ret != 0)
972de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz					goto done;
973e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			}
974e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		}
975dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
976de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		snd_pcm_sw_params_free(swparams);
977e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
9786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
979dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	while (frames_left > 0) {
980dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		frame_size = areas->step / 8;
9816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
982dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if ((data->count + frames_left * frame_size) <= a2dp->codesize)
983dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			frames_to_read = frames_left;
984dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		else
985dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			frames_to_read = (a2dp->codesize - data->count) / frame_size;
9866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
987dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
988d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		DBG("a2dp.count=%d data.link_mtu=%d", a2dp->count, data->link_mtu);
9896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* FIXME: If state is not streaming then return */
9916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
992dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Ready for more data */
993dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		buff = (uint8_t *) areas->addr +
994dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			(areas->first + areas->step * (offset + ret)) / 8;
995dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		memcpy(data->buffer + data->count, buff,
996dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				frame_size * frames_to_read);
9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
998dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Remember we have some frames in the pipe now */
999dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->count += frames_to_read * frame_size;
1000dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (data->count != a2dp->codesize) {
1001dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			ret = frames_to_read;
1002dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1003dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1005dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Enough data to encode (sbc wants 1k blocks) */
1006397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize,
1007fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					a2dp->buffer + a2dp->count,
1008fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					sizeof(a2dp->buffer) - a2dp->count,
1009397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz					&written);
1010dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (encoded <= 0) {
1011dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Encoding error %d", encoded);
1012dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1013dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1015dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->count -= encoded;
1016397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->count += written;
1017397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->frame_count++;
1018397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->samples += encoded / frame_size;
1019397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->nsamples += encoded / frame_size;
10206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1021397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		DBG("encoded=%d  written=%d count=%d", encoded,
1022397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz				written, a2dp->count);
1023dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1024397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		/* No space left for another frame then send */
1025d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (a2dp->count + written >= data->link_mtu) {
1026dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			avdtp_write(data);
1027d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("sending packet %d, count %d, link_mtu %u",
1028d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					a2dp->seq_num, a2dp->count,
1029d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					data->link_mtu);
1030f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg		}
10316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1032dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		ret += frames_to_read;
1033dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		frames_left -= frames_to_read;
1034dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
1035dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1036dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	/* note: some ALSA apps will get confused otherwise */
1037dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret > size)
1038dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		ret = size;
10396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
1041e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("returning %ld", ret);
10428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
10438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
10448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
10456967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
10466967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg					snd_pcm_sframes_t *delayp)
1047a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{
1048a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	DBG("");
1049a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
1050a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This updates io->hw_ptr value using pointer() function */
1051a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	snd_pcm_hwsync(io->pcm);
10526967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1053a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	*delayp = io->appl_ptr - io->hw_ptr;
1054a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
1055a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->callback->stop(io);
1056a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->state = SND_PCM_STATE_XRUN;
1057a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		*delayp = 0;
1058a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	}
10596967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1060a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This should never fail, ALSA API is really not
1061a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	prepared to handle a non zero return value */
1062a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	return 0;
1063a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley}
1064a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
10656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
1066892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1067892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1068e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1069e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1070721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1071e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1072e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_write,
1073892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1074892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1075a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
10766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
10776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
1079e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1080e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1081e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1082e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1083721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1084e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1085e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_read,
1086e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1087e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1088b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1089b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
10906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
1091892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1092892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1093e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1094e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1095e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1096e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1097e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_write,
1098892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1099892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1100a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
11016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
1104e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1105e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1106e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1107e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1108e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1109e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1110e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_read,
1111e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1112e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1113b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1114b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1115b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
1116b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
111733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
1118b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1119c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1120b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
1121b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
1122b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
1123b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
1124b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
1125b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
1126b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
1128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_FORMAT_S16_LE
1129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1130d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1131b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1132c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
1133b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1134b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
1135b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1136b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1137b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1138c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
1139b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1140b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
1141b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1142b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1143b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1144c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
1145c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1146d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							1, 1);
1147b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1148b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1149b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
115035b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
1151c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1152d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							8000, 8000);
1153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
115635b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
1157c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1158d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						data->link_mtu, data->link_mtu);
1159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1160b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1162c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1163f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann									2, 200);
116433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
116533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
116633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
116733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	return 0;
116833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz}
116933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
117033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
117133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{
117233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1173d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
117433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	snd_pcm_access_t access_list[] = {
117533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_RW_INTERLEAVED,
117633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		/* Mmap access is really useless fo this driver, but we
117733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * support it because some pieces of software out there
117833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * insist on using it */
117933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_MMAP_INTERLEAVED
118033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
118133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	unsigned int format_list[] = {
118233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_FORMAT_S16_LE
118333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
1184d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_list[4];
1185d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_count;
1186d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err, min_channels, max_channels;
1187dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	unsigned int period_list[] = {
1188db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		2048,
1189db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
1190db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		8192
1191dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	};
119233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
119333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* access type */
119433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
119533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(access_list), access_list);
119633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
119733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
119833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
119933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported formats */
120033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
120133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(format_list), format_list);
120233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
120333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
120433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
120533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported channels */
1206d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
1207d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 1;
1208d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1209d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 2;
121033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1211d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode & (~BT_A2DP_CHANNEL_MODE_MONO))
1212d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 2;
1213d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1214d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 1;
1215d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1216d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1217d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							min_channels, max_channels);
121833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
121933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
122033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1221db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported buffer sizes
1222db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
1223db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1224db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg					      8192*3, 8192*3);
122583a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg	if (err < 0)
122683a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg		return err;
122783a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg
1228db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported block sizes: */
1229db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1230db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg				ARRAY_NELEMS(period_list), period_list);
1231b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1232b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1233b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1234d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* supported rates */
1235d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rate_count = 0;
1236489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency &
1237489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			BT_SBC_SAMPLING_FREQ_16000) {
1238d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 16000;
1239d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1240ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	}
1241ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
1242489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency &
1243489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			BT_SBC_SAMPLING_FREQ_32000) {
1244d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 32000;
1245d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1246c4e21c814832ea94f64821a2360a28074d03be1aJohan Hedberg	}
1247ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
1248489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency &
1249489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			BT_SBC_SAMPLING_FREQ_44100) {
1250d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 44100;
1251d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
12526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
125300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1254489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency &
1255489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz			BT_SBC_SAMPLING_FREQ_48000) {
1256d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 48000;
1257d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1258d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
125900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1260d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
1261db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg						rate_count, rate_list);
1262d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1263d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1264e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
12656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
12666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
12676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1268d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf,
1269d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				struct bluetooth_alsa_config *bt_config)
12706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
127192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_iterator_t i, next;
12729fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	const char *addr, *pref, *autoconnect;
1273f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann	const char *mode, *allocation, *rate, *subbands, *blocks, *bitpool;
127492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1275d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
1276ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg
12779fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	/* Set defaults */
12789fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	bt_config->autoconnect = 1;
12799fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
128092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_for_each(i, next, conf) {
128192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		snd_config_t *n = snd_config_iterator_entry(i);
128292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		const char *id;
128392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
128492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (snd_config_get_id(n, &id) < 0)
128592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
128692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
128792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
128892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
128992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
12909fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		if (strcmp(id, "autoconnect") == 0) {
12919fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			if (snd_config_get_string(n, &autoconnect) < 0) {
12929fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				SNDERR("Invalid type for %s", id);
12939fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				return -EINVAL;
12949fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			}
12959fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
12969fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			if (strcmp(autoconnect, "no") == 0)
12979fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg				bt_config->autoconnect = 0;
12989fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg			continue;
12999fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		}
13009fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg
1301b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
130292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			if (snd_config_get_string(n, &addr) < 0) {
130392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
130492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
130592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1306b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_device = 1;
1308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strncpy(bt_config->device, addr, 18);
130992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
131092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
131192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1312b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "profile") == 0) {
131392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			if (snd_config_get_string(n, &pref) < 0) {
131492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
131592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
131692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1317b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1318d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			if (strcmp(pref, "auto") == 0) {
1319d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1320d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1321d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			} else if (strcmp(pref, "voice") == 0 ||
132241b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz						strcmp(pref, "hfp") == 0) {
1323d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1324d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1325f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann			} else if (strcmp(pref, "hifi") == 0 ||
1326d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						strcmp(pref, "a2dp") == 0) {
1327d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1328d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1329d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
133092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
133192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
133292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
13335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "rate") == 0) {
13345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &rate) < 0) {
13355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13385402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->rate = atoi(rate);
1340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_rate = 1;
13415402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
134441b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz		if (strcmp(id, "mode") == 0) {
13455402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &mode) < 0) {
13465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
135072947933a64f92a798567e74e75c0222375ae599Brad Midgley			if (strcmp(mode, "auto") == 0) {
1351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO;
1352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
135372947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "mono") == 0) {
1354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
1355d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
135672947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "dual") == 0) {
1357d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
1358d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
135972947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "stereo") == 0) {
1360d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
1361d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
136272947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "joint") == 0) {
1363d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
1364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
13665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "allocation") == 0) {
13705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &allocation) < 0) {
13715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13745402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
137572947933a64f92a798567e74e75c0222375ae599Brad Midgley			if (strcmp(allocation, "auto") == 0) {
1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_AUTO;
1377d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
137872947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(allocation, "loudness") == 0) {
1379d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
1380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
138172947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(allocation, "snr") == 0) {
1382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
1383d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1384d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
13855402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13865402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "subbands") == 0) {
13895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &subbands) < 0) {
13905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->subbands = atoi(subbands);
1395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_subbands = 1;
13965402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "blocks") == 0) {
14005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &blocks) < 0) {
14015402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1405d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->block_length = atoi(blocks);
1406d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_block_length = 1;
14075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
14105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "bitpool") == 0) {
14115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &bitpool) < 0) {
14125402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
14135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
14145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
14155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1416d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->bitpool = atoi(bitpool);
1417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_bitpool = 1;
14185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
14195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
142192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		SNDERR("Unknown field %s", id);
142292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		return -EINVAL;
142392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	}
142492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return 0;
14265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
14275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1428d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
14295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
14316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1432d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("sending %s", bt_audio_strmsg(msg->msg_type));
1433d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
1434d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = 0;
1435d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else {
1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1437d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error sending data to audio service: %s(%d)",
1438d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strerror(errno), errno);
14398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
1440b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1441d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
14436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1444d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
1445d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
1446d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	const char *type;
1448d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1449d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("trying to receive msg from audio service...");
1450d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
1451d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		type = bt_audio_strmsg(inmsg->msg_type);
1452d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (type) {
1453d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("Received %s", type);
1454d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = 0;
1455d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		} else {
1456d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
1457d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			SNDERR("Bogus message type %d "
1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					"received from audio service",
1459d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					inmsg->msg_type);
1460d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
1461d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
1462d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1463d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error receiving data from audio service: %s(%d)",
1464d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					strerror(errno), errno);
14656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
14668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1467d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1468d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
1469dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg
1470d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr,
1471d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				int expected_type)
1472d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
1473d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	int err = audioservice_recv(sk, rsp_hdr);
1474d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err == 0) {
1475d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		if (rsp_hdr->msg_type != expected_type) {
1476d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
1477d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			SNDERR("Bogus message %s received while "
1478d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					"%s was expected",
1479d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					bt_audio_strmsg(rsp_hdr->msg_type),
1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					bt_audio_strmsg(expected_type));
1481d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
1482f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
1483d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
14848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
14858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1486ec384afacde8614306abe32cf40c55b795783f0eJohan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,
1487ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg				snd_config_t *conf)
14888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
14896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
1490d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
1491d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
1492d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
1493d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_getcapabilities_req *getcaps_req = (void*) buf;
1494d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf;
1495f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
149600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
149700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1498d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = bluetooth_parse_config(conf, alsa_conf);
1499d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1500d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1501d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1502e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = -1;
1503dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg	data->stream.fd = -1;
150400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1505d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sk = bt_audio_service_open();
1506e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley	if (sk <= 0) {
1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1508d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1509b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1510b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1511e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = sk;
1512e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.events = POLLIN;
1513b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1514892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[0] = -1;
1515892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[1] = -1;
1516892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1517d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (pipe(data->pipefd) < 0) {
1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1519d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1520d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1521d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
1522d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1523d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1525d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
1526d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1527d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1528d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1529d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1530d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ;
15329fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	getcaps_req->flags = 0;
15339fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg	if (alsa_conf->autoconnect)
15349fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg		getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
1535d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	strncpy(getcaps_req->device, alsa_conf->device, 18);
1536d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (alsa_conf->has_transport)
1537d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		getcaps_req->transport = alsa_conf->transport;
1538d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1539d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1540721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
1541d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &getcaps_req->h);
1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1543d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1544d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1545d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, BT_GETCAPABILITIES_RSP);
1546d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1547d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1548d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1549d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
1550d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_GETCAPABILITIES failed : %s(%d)",
1551d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
1552d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
1553d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
1554d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1555d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1556d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->transport = getcaps_rsp->transport;
1557721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
1558d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
1559d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities;
1560892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1561d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
1562d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1563d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed:
1564d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	bt_audio_service_close(sk);
1565d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
15668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
15678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
15688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
15698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1570f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
15718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
15728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
157300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
15748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
15758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1576d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg	data = malloc(sizeof(struct bluetooth_data));
157700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
157800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
157900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
158000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
158100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1582ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg	err = bluetooth_init(data, stream, conf);
15838742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
15848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
15858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1586f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
1587f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
158800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
1589f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
1590b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1591d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
15926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
15936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
15946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
15956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
15966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
15976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
15986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
15996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1600f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
1601b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1602b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
1603b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1604d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
160533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_a2dp_hw_constraint(&data->io);
160633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	else
160733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_hsp_hw_constraint(&data->io);
160833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1609b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
1610f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
16118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
1612b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1613b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1614f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
1615b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1616b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
1617b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1618b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
16195ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
16205ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
1621b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
16225ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
16235ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
16245ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
1625