pcm_bluetooth.c revision e65858be07f86fe12756c67a20a5f45debfcc250
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;
1256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
1266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data {
128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_ioplug_t io;
129d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config alsa_config;	/* ALSA resource file parameters */
130e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	volatile snd_pcm_sframes_t hw_ptr;
131d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int transport;					/* chosen transport SCO or AD2P */
132d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int link_mtu;					/* MTU for selected transport channel */
133d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	volatile struct pollfd stream;			/* Audio stream filedescriptor */
134d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct pollfd server;				/* Audio daemon filedescriptor */
135d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint8_t buffer[BUFFER_SIZE];		/* Encoded transfer buffer */
136d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int count;					/* Transfer buffer counter */
137d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp a2dp;			/* A2DP data */
138d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
139d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	pthread_t hw_thread;				/* Makes virtual hw pointer move */
140d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int pipefd[2];					/* Inter thread communication */
141892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	int stopped;
142dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	sig_atomic_t reset;             /* Request XRUN handling */
143b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
145d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg);
146d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg,
147d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				int expected_type);
148d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
149b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io)
150b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1519217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_start %p", io);
152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
156b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io)
157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_stop %p", io);
159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
160b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
163892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic void *playback_hw_thread(void *param)
164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = param;
166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	unsigned int prev_periods;
167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	double period_time;
168d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	struct timespec start;
169e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	struct pollfd fds[2];
1703e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	int poll_timeout;
171e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
172dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->server.events = POLLIN;
173dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	/* note: only errors for data->stream.events */
174dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
175e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[0] = data->server;
176e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	fds[1] = data->stream;
177e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	prev_periods = 0;
179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	period_time = 1000000.0 * data->io.period_size / data->io.rate;
1803e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	if (period_time > (int) (MIN_PERIOD_TIME * 1000))
1813e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = (int) (period_time / 1000.0f);
1823e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg	else
1833e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		poll_timeout = MIN_PERIOD_TIME;
184e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
185d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg	clock_gettime(CLOCK_MONOTONIC, &start);
186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	while (1) {
188714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg		unsigned int dtime, periods;
189d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		struct timespec cur, delta;
190e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		int ret;
191e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
192892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (data->stopped)
193f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg			goto iter_sleep;
194f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
195dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (data->reset) {
196dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Handle XRUN in hw-thread.");
197dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->reset = 0;
198d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg			clock_gettime(CLOCK_MONOTONIC, &start);
199dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			prev_periods = 0;
200dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
201dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
202d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		clock_gettime(CLOCK_MONOTONIC, &cur);
203e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
204d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		priv_timespecsub(&cur, &start, &delta);
205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
206d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg		dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000;
207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		periods = 1.0 * dtime / period_time;
208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		if (periods > prev_periods) {
210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			char c = 'w';
211dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			int frags = periods - prev_periods, n;
212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
213dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			data->hw_ptr += frags *	data->io.period_size;
214e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			data->hw_ptr %= data->io.buffer_size;
215e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
216dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			for (n = 0; n < frags; n++) {
217dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				/* Notify user that hardware pointer
218dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				 * has moved * */
219dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				if (write(data->pipefd[1], &c, 1) < 0)
220dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					pthread_testcancel();
221dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			}
222e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
223714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			/* Reset point of reference to avoid too big values
224714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg			 * that wont fit an unsigned int */
2258dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			if (delta.tv_sec < UINT_SECS_MAX)
2268dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg				prev_periods = periods;
2278dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			else {
228714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg				prev_periods = 0;
229d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg				clock_gettime(CLOCK_MONOTONIC, &start);
2308dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg			}
231de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		}
232e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
233f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedbergiter_sleep:
2343e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		/* sleep up to one period interval */
2353e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg		ret = poll(fds, 2, poll_timeout);
236dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
237e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		if (ret < 0) {
238e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll error: %s (%d)", strerror(errno), errno);
239e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			if (errno != EINTR)
240e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
241e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		} else if (ret > 0) {
242e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			ret = (fds[0].revents) ? 0 : 1;
243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz			SNDERR("poll fd %d revents %d", ret, fds[ret].revents);
244db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann			if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL))
245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz				break;
246e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		}
247e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
248e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		/* Offer opportunity to be canceled by main thread */
249de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		pthread_testcancel();
250e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
251e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz
252e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->hw_thread = 0;
253e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pthread_exit(NULL);
254e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
25533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
256892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io)
257e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
259e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int err;
260e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
263892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 0;
264f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
265892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread)
266f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		return 0;
267e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
268892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data);
269e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
270e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return -err;
271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
273892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io)
274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
275e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
277e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("%p", io);
278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
279892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->stopped = 1;
280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
2817090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg	return 0;
282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
283e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
284b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
285b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return data->hw_ptr;
289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
2915ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data)
2925ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{
293892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
294892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
295e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->server.fd >= 0)
296d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		bt_audio_service_close(data->server.fd);
2975ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
298e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	if (data->stream.fd >= 0)
299e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz		close(data->stream.fd);
3002a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz
301892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->hw_thread) {
302892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
303892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
304892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
305f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg
306d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
307f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg		sbc_finish(&a2dp->sbc);
308d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz
309892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[0] > 0)
310892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[0]);
311de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
312892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (data->pipefd[1] > 0)
313892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		close(data->pipefd[1]);
314de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
3155ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	free(data);
3165ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz}
3175ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
318b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io)
319b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
321b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("%p", io);
323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3245ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
326b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
328b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
3298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io)
3308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
332e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	char c = 'w';
333d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
334d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_streamstart_req *start_req = (void*) buf;
335d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
336d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	struct bt_streamfd_ind *streamfd_ind = (void*) buf;
337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int opt_name, err;
339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct timeval t = { 0, period_count };
3408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
34138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
34238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					io->period_size, io->buffer_size);
3438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
344dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	data->reset = 0;
345dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
346d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* As we're gonna receive messages on the server socket, we have to stop the
347d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	   hw thread that is polling on it, if any */
348d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->hw_thread) {
349d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_cancel(data->hw_thread);
350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		pthread_join(data->hw_thread, 0);
351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->hw_thread = 0;
352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
3549217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	if (io->stream == SND_PCM_STREAM_PLAYBACK)
35500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* If not null for playback, xmms doesn't display time
35600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * correctly */
3578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = 0;
3589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	else
35900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* ALSA library is really picky on the fact hw_ptr is not null.
36000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * If it is, capture won't start */
3618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = io->period_size;
3629217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
363d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* send start */
364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	start_req->h.msg_type = BT_STREAMSTART_REQ;
3668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &start_req->h);
368d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
369d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
370d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
371d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
372d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_STREAMSTART_RSP);
373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
376d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
377d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_START failed : %s(%d)",
378d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
379d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
380d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
383d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &streamfd_ind->h,
384d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_STREAMFD_IND);
385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd >= 0)
389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		close(data->stream.fd);
390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->stream.fd < 0) {
393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return -errno;
394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
3959217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						SO_SNDTIMEO : SO_RCVTIMEO;
399ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
400d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							sizeof(t)) < 0)
402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return -errno;
403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
404d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
40538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SCO_TXBUFS : SCO_RXBUFS;
4068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
407d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
40838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
409d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4109217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
411d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
41238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						SO_SNDBUF : SO_RCVBUF;
41300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
41538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann						sizeof(period_count)) == 0)
416d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			return 0;
4177090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg
418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		/* FIXME : handle error codes */
419d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
42000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* wake up any client polling at us */
422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return write(data->pipefd[1], &c, 1);
4238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
4248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
425721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
426721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
427721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{
428721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
429721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bt_setconfiguration_req *setconf_req = (void*) buf;
432721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
433721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	int err;
434721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
435721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
436721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					io->period_size, io->buffer_size);
437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	strncpy(setconf_req->device, data->alsa_config.device, 18);
441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_SCO;
442721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
443721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
444721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
445721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
446721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	err = audioservice_send(data->server.fd, &setconf_req->h);
447721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
448721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
449721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
450721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
451721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					BT_SETCONFIGURATION_RSP);
452721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (err < 0)
453721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return err;
454721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
455721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
456721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		SNDERR("BT_SETCONFIGURATION failed : %s(%d)",
457721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
458721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz					rsp_hdr->posix_errno);
459721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz		return -rsp_hdr->posix_errno;
460721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	}
461721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
462721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	data->transport = setconf_rsp->transport;
463721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	data->link_mtu = setconf_rsp->link_mtu;
464721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
465721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	return 0;
466721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz}
467721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
4682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
4692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
4702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (freq) {
4712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case BT_A2DP_SAMPLING_FREQ_16000:
4722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case BT_A2DP_SAMPLING_FREQ_32000:
4732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
4742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case BT_A2DP_SAMPLING_FREQ_44100:
4752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
4782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 31;
4792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
4802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
4812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
4822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
4832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
4842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 53;
4852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
4862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case BT_A2DP_SAMPLING_FREQ_48000:
4872934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		switch (mode) {
4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_MONO:
4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 29;
4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_STEREO:
4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
4942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		default:
4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			DBG("Invalid channel mode %u", mode);
4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			return 51;
4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		}
4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Invalid sampling freq %u", freq);
5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return 53;
5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic int select_sbc_params(sbc_capabilities_t *cap, unsigned int rate,
5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz				unsigned int channels)
5062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{
5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	unsigned int max_bitpool, min_bitpool;
5082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	switch (rate) {
5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 48000:
5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->frequency = BT_A2DP_SAMPLING_FREQ_48000;
5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 44100:
5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->frequency = BT_A2DP_SAMPLING_FREQ_44100;
5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 32000:
5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->frequency = BT_A2DP_SAMPLING_FREQ_32000;
5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	case 16000:
5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->frequency = BT_A2DP_SAMPLING_FREQ_16000;
5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		break;
5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	default:
5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("Rate %d not supported", rate);
5242934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (channels == 2) {
5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
5292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
5302934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
5312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
5322934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
5332934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
5342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	} else {
5352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (!cap->channel_mode) {
5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported channel modes");
5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5532934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported block lengths");
5542934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5552934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->subbands & BT_A2DP_SUBBANDS_8)
5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_8;
5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->subbands = BT_A2DP_SUBBANDS_4;
5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else {
5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		DBG("No supported subbands");
5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return -1;
5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	}
5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz							cap->max_bitpool);
5742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->min_bitpool = min_bitpool;
5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	cap->max_bitpool = max_bitpool;
5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	return 0;
5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz}
5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
582afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
583afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
584afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
585afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
586d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
587d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
588d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
589d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_setconfiguration_req *setconf_req = (void*) buf;
590d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	unsigned int rate, channels;
5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	int err, dir;
593d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sbc_capabilities_t active_capabilities;
594afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
595d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
596d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					io->period_size, io->buffer_size);
597afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
598d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* FIXME: this needs to be really implemented (take into account
599d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	real asoundrc settings + ALSA hw settings ) once server side sends us
600d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	more than one possible configuration */
6012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	snd_pcm_hw_params_get_rate(params, &rate, &dir);
6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	snd_pcm_hw_params_get_channels(params, &channels);
6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	err = select_sbc_params(&a2dp->sbc_capabilities, rate, channels);
6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	if (err < 0)
6052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		return err;
6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
607d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	active_capabilities = a2dp->sbc_capabilities;
608afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
610d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
611721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	strncpy(setconf_req->device, data->alsa_config.device, 18);
612721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
613d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	setconf_req->sbc_capabilities = active_capabilities;
6142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?
6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_WRITE :
6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz			BT_CAPABILITIES_ACCESS_MODE_READ);
617afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
618d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &setconf_req->h);
619d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
620d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
621e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
622d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h,
623d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					BT_SETCONFIGURATION_RSP);
624d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
625d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
626afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
627d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_SETCONFIGURATION failed : %s(%d)",
629d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
630d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
631d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
633d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
6342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	data->transport = setconf_rsp->transport;
6352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	data->link_mtu = setconf_rsp->link_mtu;
6362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* Setup SBC encoder now we agree on parameters */
638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_initialized)
6392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_reinit(&a2dp->sbc, 0);
6402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz	else
6412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz		sbc_init(&a2dp->sbc, 0);
642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc_initialized = 1;
6432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz
644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000)
645d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 16000;
646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000)
648d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 32000;
649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
650d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100)
651d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 44100;
652d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000)
654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.rate = 48000;
655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.channels = 1;
658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.channels = 2;
660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (active_capabilities.channel_mode &
662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			(BT_A2DP_CHANNEL_MODE_MONO || BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.joint = 1;
664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.joint = 0;
666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.allocation = active_capabilities.allocation_method
668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					== BT_A2DP_ALLOCATION_SNR ? 0x01 : 0x00;
669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.subbands) {
671d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_4:
672d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.subbands = 4;
673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_SUBBANDS_8:
675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.subbands = 8;
676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	switch (active_capabilities.block_length) {
680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_4:
681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 4;
682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_8:
684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 8;
685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_12:
687d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 12;
688d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
689d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	case BT_A2DP_BLOCK_LENGTH_16:
690d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.blocks = 16;
691d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		break;
692d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
693d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
694d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->sbc.bitpool = active_capabilities.max_bitpool;
695d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->codesize = a2dp->sbc.subbands * a2dp->sbc.blocks *
696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						a2dp->sbc.channels * 2;
697d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
698d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
699d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks,
701d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		a2dp->sbc.bitpool);
702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
703d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
704afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
705afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
706e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io,
707f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann					struct pollfd *pfd, unsigned int space)
708e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
709e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
710e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
711e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(io);
712e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
713e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
714e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
715e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
716e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	pfd[0].fd = data->stream.fd;
717e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
718e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
719e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
720e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
721e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
722e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
723e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg					struct pollfd *pfds, unsigned int nfds,
725dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
727e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds && nfds == 1 && revents);
728e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
729e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = pfds[0].revents;
730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
734892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,
73538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfd, unsigned int space)
736e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
737e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	struct bluetooth_data *data = io->private_data;
738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
739e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
740e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
741892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	assert(data->pipefd[0] >= 0);
742e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
743e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (space < 1)
744e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		return 0;
745e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
746892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	pfd[0].fd = data->pipefd[0];
747e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].events = POLLIN;
748e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	pfd[0].revents = 0;
749e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
750e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 1;
751e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
752e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
753892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,
75438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann					struct pollfd *pfds, unsigned int nfds,
755dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg					unsigned short *revents)
756e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{
757e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	static char buf[1];
758e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret;
759e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
760e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("");
761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
762e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds);
763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(nfds == 1);
764e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(revents);
765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	assert(pfds[0].fd >= 0);
766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	if (io->state != SND_PCM_STATE_PREPARED)
768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = read(pfds[0].fd, buf, 1);
769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	*revents = (pfds[0].revents & ~POLLIN) | POLLOUT;
771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	return 0;
773e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg}
774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
77738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
778dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
779dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
7808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
7818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
78200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
78300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
784f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int nrecv, frame_size = 0;
7858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
78638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",
78738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
7888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
7893709666344736da68472f754ac52edc356039058Johan Hedberg	frame_size = areas->step / 8;
7903709666344736da68472f754ac52edc356039058Johan Hedberg
79100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
79200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
79300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
794d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	nrecv = recv(data->stream.fd, data->buffer, data->link_mtu,
79500c71248e732de0230c12df4240087a6b2747179Johan Hedberg			MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0));
79600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
79700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
79800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
79900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
80100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
802d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (nrecv != data->link_mtu) {
80300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
80400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
80500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
80800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
809d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) %
810721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz				io->buffer_size;
81100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
81200c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
8136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
8146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
81500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
816d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
81700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
81800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
819d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_write = (data->link_mtu - data->count) / frame_size;
82000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
821f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
822f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
823d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->count %= data->link_mtu;
82400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
82500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
82600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
82700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
82800c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
82900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
8308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
8318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
8328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
83438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
835dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
836dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
8398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
8408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
841c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
842f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
8438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
84438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",
84538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann			areas->step, areas->first, offset, size, io->nonblock);
8468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
847892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	if (io->hw_ptr > io->appl_ptr) {
848892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
849892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		if (ret == 0)
850892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz			ret = -EPIPE;
851892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		goto done;
852892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	}
853892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
854f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
855d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= data->link_mtu)
8568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
8578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
858d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		frames_to_read = (data->link_mtu - data->count) / frame_size;
8598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
86038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
861c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
8628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
8636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
865f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
8668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
8682a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
869d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->count != data->link_mtu) {
8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
8728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
8738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
874d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rsend = send(data->stream.fd, data->buffer, data->link_mtu,
875c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
87600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
87700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
87800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
87900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
88200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
88300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
88400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
88600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
887892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	DBG("returning %ld", ret);
8886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
8896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
8916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
89238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
893dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t offset,
894dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				snd_pcm_uframes_t size)
8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
8966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
8976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
8996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
900e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data)
9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
902e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	int ret = 0;
9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
9046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
9059494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
9086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
9096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
9116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
9136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
9146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
9156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
9166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
9176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
9186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
919dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg        ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);
920dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret < 0) {
921dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("send returned %d errno %s.", ret, strerror(errno));
922e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		ret = -errno;
923dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
9248905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg
9256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
931f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg	return ret;
9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
93538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				const snd_pcm_channel_area_t *areas,
93638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
9386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
941dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	snd_pcm_uframes_t frames_to_read, frames_left = size;
942397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz	int frame_size, encoded, written;
9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
9446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
94538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",
94638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann				areas->step, areas->first, offset, size);
947dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr,
948dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			io->appl_ptr - io->hw_ptr);
949e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
950cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->hw_ptr > io->appl_ptr) {
951892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz		ret = bluetooth_playback_stop(io);
952de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		if (ret == 0)
953e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			ret = -EPIPE;
954dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->reset = 1;
955de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		goto done;
956de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz	}
957e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
958e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	/* Check if we should autostart */
959cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg	if (io->state == SND_PCM_STATE_PREPARED) {
960e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_t *swparams;
961e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_uframes_t threshold;
962de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz
963e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		snd_pcm_sw_params_malloc(&swparams);
96438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&
965dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				!snd_pcm_sw_params_get_start_threshold(swparams,
966dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg								&threshold)) {
967cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg			if (io->appl_ptr >= threshold) {
968e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg				ret = snd_pcm_start(io->pcm);
969cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg				if (ret != 0)
970de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz					goto done;
971e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg			}
972e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg		}
973dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
974de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz		snd_pcm_sw_params_free(swparams);
975e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	}
9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
977dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	while (frames_left > 0) {
978dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		frame_size = areas->step / 8;
9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
980dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if ((data->count + frames_left * frame_size) <= a2dp->codesize)
981dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			frames_to_read = frames_left;
982dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		else
983dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			frames_to_read = (a2dp->codesize - data->count) / frame_size;
9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
985dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);
986d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		DBG("a2dp.count=%d data.link_mtu=%d", a2dp->count, data->link_mtu);
9876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
988dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* FIXME: If state is not streaming then return */
9896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Ready for more data */
991dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		buff = (uint8_t *) areas->addr +
992dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			(areas->first + areas->step * (offset + ret)) / 8;
993dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		memcpy(data->buffer + data->count, buff,
994dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg				frame_size * frames_to_read);
9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
996dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Remember we have some frames in the pipe now */
997dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->count += frames_to_read * frame_size;
998dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (data->count != a2dp->codesize) {
999dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			ret = frames_to_read;
1000dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1001dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1003dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		/* Enough data to encode (sbc wants 1k blocks) */
1004397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize,
1005fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					a2dp->buffer + a2dp->count,
1006fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz					sizeof(a2dp->buffer) - a2dp->count,
1007397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz					&written);
1008dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		if (encoded <= 0) {
1009dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			DBG("Encoding error %d", encoded);
1010dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			goto done;
1011dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		}
10126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1013dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		data->count -= encoded;
1014397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->count += written;
1015397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->frame_count++;
1016397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->samples += encoded / frame_size;
1017397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		a2dp->nsamples += encoded / frame_size;
10186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1019397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		DBG("encoded=%d  written=%d count=%d", encoded,
1020397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz				written, a2dp->count);
1021dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1022397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz		/* No space left for another frame then send */
1023d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (a2dp->count + written >= data->link_mtu) {
1024dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg			avdtp_write(data);
1025d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("sending packet %d, count %d, link_mtu %u",
1026d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					a2dp->seq_num, a2dp->count,
1027d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					data->link_mtu);
1028f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg		}
10296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1030dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		ret += frames_to_read;
1031dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		frames_left -= frames_to_read;
1032dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	}
1033dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg
1034dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	/* note: some ALSA apps will get confused otherwise */
1035dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	if (ret > size)
1036dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg		ret = size;
10376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
1039e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	DBG("returning %ld", ret);
10408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
10418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
10428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
10436967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io,
10446967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg					snd_pcm_sframes_t *delayp)
1045a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{
1046a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	DBG("");
1047a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
1048a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This updates io->hw_ptr value using pointer() function */
1049a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	snd_pcm_hwsync(io->pcm);
10506967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1051a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	*delayp = io->appl_ptr - io->hw_ptr;
1052a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) {
1053a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->callback->stop(io);
1054a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		io->state = SND_PCM_STATE_XRUN;
1055a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley		*delayp = 0;
1056a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	}
10576967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg
1058a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	/* This should never fail, ALSA API is really not
1059a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	prepared to handle a non zero return value */
1060a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	return 0;
1061a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley}
1062a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley
10636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
1064892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1065892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1066e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1067e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1068721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1069e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1070e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_write,
1071892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1072892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1073a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
10746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
10756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
10766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
1077e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1078e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1079e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1080e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1081721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz	.hw_params		= bluetooth_hsp_hw_params,
1082e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1083e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_hsp_read,
1084e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1085e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1086b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1087b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
10886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
1089892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.start			= bluetooth_playback_start,
1090892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.stop			= bluetooth_playback_stop,
1091e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1092e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1093e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1094e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1095e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_write,
1096892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_descriptors	= bluetooth_playback_poll_descriptors,
1097892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	.poll_revents		= bluetooth_playback_poll_revents,
1098a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley	.delay			= bluetooth_playback_delay,
10996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
11006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
11016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
1102e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.start			= bluetooth_start,
1103e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.stop			= bluetooth_stop,
1104e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.pointer		= bluetooth_pointer,
1105e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.close			= bluetooth_close,
1106e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.hw_params		= bluetooth_a2dp_hw_params,
1107e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.prepare		= bluetooth_prepare,
1108e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.transfer		= bluetooth_a2dp_read,
1109e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_descriptors	= bluetooth_poll_descriptors,
1110e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg	.poll_revents		= bluetooth_poll_revents,
1111b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
1112b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1113b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
1114b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
111533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)
1116b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1117c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1118b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
1119b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
1120b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
1121b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
1122b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
1123b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
1124b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1125b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
1126b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_FORMAT_S16_LE
1127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
1128d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1130c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
1131b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1132b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
1133b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1134b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1135b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1136c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
1137b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1138b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
1139b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1140b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1141b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1142c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
1143c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1144d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							1, 1);
1145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1146b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1147b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
114835b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
1149c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1150d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							8000, 8000);
1151b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
115435b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
1155c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1156d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						data->link_mtu, data->link_mtu);
1157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1160c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1161f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann									2, 200);
116233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
116333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
116433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
116533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	return 0;
116633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz}
116733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
116833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)
116933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{
117033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1171d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_a2dp *a2dp = &data->a2dp;
117233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	snd_pcm_access_t access_list[] = {
117333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_RW_INTERLEAVED,
117433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		/* Mmap access is really useless fo this driver, but we
117533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * support it because some pieces of software out there
117633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		 * insist on using it */
117733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_ACCESS_MMAP_INTERLEAVED
117833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
117933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	unsigned int format_list[] = {
118033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		SND_PCM_FORMAT_S16_LE
118133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	};
1182d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_list[4];
1183d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	unsigned int rate_count;
1184d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err, min_channels, max_channels;
1185dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	unsigned int period_list[] = {
1186db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		2048,
1187db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */
1188db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg		8192
1189dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg	};
119033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
119133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* access type */
119233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
119333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(access_list), access_list);
119433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
119533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
119633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
119733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported formats */
119833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
119933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz					ARRAY_NELEMS(format_list), format_list);
120033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
120133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
120233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
120333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	/* supported channels */
1204d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
1205d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 1;
1206d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1207d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		min_channels = 2;
120833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1209d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.channel_mode & (~BT_A2DP_CHANNEL_MODE_MONO))
1210d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 2;
1211d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1212d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		max_channels = 1;
1213d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1214d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1215d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz							min_channels, max_channels);
121633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	if (err < 0)
121733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		return err;
121833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1219db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported buffer sizes
1220db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	 * (can be used as 3*8192, 6*4096, 12*2048, ...) */
1221db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1222db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg					      8192*3, 8192*3);
122383a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg	if (err < 0)
122483a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg		return err;
122583a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg
1226db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	/* supported block sizes: */
1227db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1228db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg				ARRAY_NELEMS(period_list), period_list);
1229b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
1231b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1232d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	/* supported rates */
1233d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	rate_count = 0;
1234d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) {
1235d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 16000;
1236d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1237ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	}
1238ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
1239d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) {
1240d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 32000;
1241d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1242c4e21c814832ea94f64821a2360a28074d03be1aJohan Hedberg	}
1243ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
1244d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) {
1245d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 44100;
1246d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
12476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
124800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1249d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) {
1250d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_list[rate_count] = 48000;
1251d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		rate_count++;
1252d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
125300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1254d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE,
1255db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg						rate_count, rate_list);
1256d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1257d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg
12596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
12606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
12616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1262d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf,
1263d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				struct bluetooth_alsa_config *bt_config)
12646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
126592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_iterator_t i, next;
1266f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann	const char *addr, *pref;
1267f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann	const char *mode, *allocation, *rate, *subbands, *blocks, *bitpool;
126892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1269d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(bt_config, 0, sizeof(struct bluetooth_alsa_config));
1270ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg
127192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	snd_config_for_each(i, next, conf) {
127292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		snd_config_t *n = snd_config_iterator_entry(i);
127392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		const char *id;
127492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
127592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (snd_config_get_id(n, &id) < 0)
127692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
127792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
127892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
127992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
128092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1281b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) {
128292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			if (snd_config_get_string(n, &addr) < 0) {
128392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
128492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
128592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1286b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1287d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_device = 1;
1288d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strncpy(bt_config->device, addr, 18);
128992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
129092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
129192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
1292b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann		if (strcmp(id, "profile") == 0) {
129392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			if (snd_config_get_string(n, &pref) < 0) {
129492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				SNDERR("Invalid type for %s", id);
129592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann				return -EINVAL;
129692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			}
1297b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann
1298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			if (strcmp(pref, "auto") == 0) {
1299d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1300d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1301d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			} else if (strcmp(pref, "voice") == 0 ||
130241b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz						strcmp(pref, "hfp") == 0) {
1303d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO;
1304d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1305f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann			} else if (strcmp(pref, "hifi") == 0 ||
1306d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz						strcmp(pref, "a2dp") == 0) {
1307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
1308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_transport = 1;
1309d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
131092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann			continue;
131192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		}
131292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
13135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "rate") == 0) {
13145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &rate) < 0) {
13155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1319d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->rate = atoi(rate);
1320d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_rate = 1;
13215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13235402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
132441b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz		if (strcmp(id, "mode") == 0) {
13255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &mode) < 0) {
13265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
133072947933a64f92a798567e74e75c0222375ae599Brad Midgley			if (strcmp(mode, "auto") == 0) {
1331d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO;
1332d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
133372947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "mono") == 0) {
1334d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
1335d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
133672947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "dual") == 0) {
1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
1338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
133972947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "stereo") == 0) {
1340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
1341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
134272947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(mode, "joint") == 0) {
1343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
1344d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_channel_mode = 1;
1345d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
13465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "allocation") == 0) {
13505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &allocation) < 0) {
13515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13525402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
135572947933a64f92a798567e74e75c0222375ae599Brad Midgley			if (strcmp(allocation, "auto") == 0) {
1356d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_AUTO;
1357d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
135872947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(allocation, "loudness") == 0) {
1359d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
1360d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
136172947933a64f92a798567e74e75c0222375ae599Brad Midgley			} else if (strcmp(allocation, "snr") == 0) {
1362d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR;
1363d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				bt_config->has_allocation_method = 1;
1364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			}
13655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "subbands") == 0) {
13695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &subbands) < 0) {
13705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->subbands = atoi(subbands);
1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_subbands = 1;
13765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "blocks") == 0) {
13805402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &blocks) < 0) {
13815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13845402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->block_length = atoi(blocks);
1386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_block_length = 1;
13875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
13895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
13905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		if (strcmp(id, "bitpool") == 0) {
13915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			if (snd_config_get_string(n, &bitpool) < 0) {
13925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				SNDERR("Invalid type for %s", id);
13935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz				return -EINVAL;
13945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			}
13955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->bitpool = atoi(bitpool);
1397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			bt_config->has_bitpool = 1;
13985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz			continue;
13995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz		}
14005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
140192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		SNDERR("Unknown field %s", id);
140292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann		return -EINVAL;
140392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann	}
140492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann
14055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz	return 0;
14065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz}
14075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz
1408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg)
14095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{
1410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
14116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1412d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("sending %s", bt_audio_strmsg(msg->msg_type));
1413d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
1414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = 0;
1415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else {
1416d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error sending data to audio service: %s(%d)",
1418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			strerror(errno), errno);
14198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
1420b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
14236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1424d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg)
1425d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	int err;
1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	const char *type;
1428d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1429d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	DBG("trying to receive msg from audio service...");
1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		type = bt_audio_strmsg(inmsg->msg_type);
1432d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		if (type) {
1433d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			DBG("Received %s", type);
1434d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = 0;
1435d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		} else {
1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
1437d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			SNDERR("Bogus message type %d "
1438d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					"received from audio service",
1439d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					inmsg->msg_type);
1440d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
1441d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	} else {
1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1443d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("Error receiving data from audio service: %s(%d)",
1444d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					strerror(errno), errno);
14456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
14468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
1448d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}
1449dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg
1450d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr,
1451d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz				int expected_type)
1452d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{
1453d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	int err = audioservice_recv(sk, rsp_hdr);
1454d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err == 0) {
1455d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		if (rsp_hdr->msg_type != expected_type) {
1456d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			err = -EINVAL;
1457d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz			SNDERR("Bogus message %s received while "
1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					"%s was expected",
1459d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					bt_audio_strmsg(rsp_hdr->msg_type),
1460d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz					bt_audio_strmsg(expected_type));
1461d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		}
1462f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
1463d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
14648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
14658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1466ec384afacde8614306abe32cf40c55b795783f0eJohan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,
1467ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg				snd_config_t *conf)
14688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
14696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
1470d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bluetooth_alsa_config *alsa_conf = &data->alsa_config;
1471d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	char buf[BT_AUDIO_IPC_PACKET_SIZE];
1472d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
1473d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_getcapabilities_req *getcaps_req = (void*) buf;
1474d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf;
1475f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
147600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
147700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1478d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = bluetooth_parse_config(conf, alsa_conf);
1479d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		return err;
1481d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1482e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = -1;
1483dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg	data->stream.fd = -1;
148400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1485d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	sk = bt_audio_service_open();
1486e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley	if (sk <= 0) {
1487d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1488d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1489b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1490b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1491e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.fd = sk;
1492e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz	data->server.events = POLLIN;
1493b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1494892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[0] = -1;
1495892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz	data->pipefd[1] = -1;
1496892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1497d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (pipe(data->pipefd) < 0) {
1498d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1499d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1500d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1501d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1503d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1504d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1505d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) {
1506d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		err = -errno;
1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1508d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1509d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1510d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
1511d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ;
1512d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	strncpy(getcaps_req->device, alsa_conf->device, 18);
1513d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (alsa_conf->has_transport)
1514d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		getcaps_req->transport = alsa_conf->transport;
1515d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	else
1516d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY;
1517721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	err = audioservice_send(data->server.fd, &getcaps_req->h);
1519d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1520d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1521d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1522d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, BT_GETCAPABILITIES_RSP);
1523d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (err < 0)
1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		goto failed;
1525d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1526d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz	if (rsp_hdr->posix_errno != 0) {
1527d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		SNDERR("BT_GETCAPABILITIES failed : %s(%d)",
1528d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					strerror(rsp_hdr->posix_errno),
1529d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz					rsp_hdr->posix_errno);
1530d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz		return -rsp_hdr->posix_errno;
1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	}
1532d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1533d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	data->transport = getcaps_rsp->transport;
1534721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz
1535d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
1536d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz		data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities;
1537892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz
1538d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return 0;
1539d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz
1540d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed:
1541d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	bt_audio_service_close(sk);
1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	return err;
15438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
15448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
15458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
15468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1547f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
15488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
15498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
155000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
15518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
15528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1553d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg	data = malloc(sizeof(struct bluetooth_data));
155400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
155500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
155600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
155700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
155800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
1559ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg	err = bluetooth_init(data, stream, conf);
15608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
15618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
15628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1563f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
1564f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
156500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
1566f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
1567b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1568d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
15696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
15706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
15716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
15726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
15736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
15746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
15756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
15766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
1577f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
1578b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
1579b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
1580b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1581d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
158233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_a2dp_hw_constraint(&data->io);
158333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz	else
158433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz		err = bluetooth_hsp_hw_constraint(&data->io);
158533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz
1586b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
1587f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
15888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
1589b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
1590b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1591f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
1592b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1593b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
1594b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1595b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
15965ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
15975ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
1598b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
15995ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
16005ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
16015ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
1602