133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/*
233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  BlueZ - Bluetooth protocol stack for Linux
433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  Copyright (C) 2006-2007  Nokia Corporation
633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  This library is free software; you can redistribute it and/or
1033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  modify it under the terms of the GNU Lesser General Public
1133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  License as published by the Free Software Foundation; either
1233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  version 2.1 of the License, or (at your option) any later version.
1333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
1433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  This library is distributed in the hope that it will be useful,
1533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  Lesser General Public License for more details.
1833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
1933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  You should have received a copy of the GNU Lesser General Public
2033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  License along with this library; if not, write to the Free Software
2133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh *
2333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh */
2433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
2533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef HAVE_CONFIG_H
2633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <config.h>
2733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
2833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
2933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <stdint.h>
3033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <sys/socket.h>
3133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <sys/un.h>
3233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <signal.h>
3333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <limits.h>
3433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <fcntl.h>
3533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <unistd.h>
3633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <pthread.h>
3733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
3833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <netinet/in.h>
3933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <sys/poll.h>
4033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <sys/prctl.h>
4133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
4282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly#include <bluetooth/bluetooth.h>
4382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly#include <bluetooth/l2cap.h>
4482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
4533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "ipc.h"
4633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "sbc.h"
4733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "rtp.h"
4833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "liba2dp.h"
4933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define LOG_NDEBUG 0
5133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define LOG_TAG "A2DP"
5233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <utils/Log.h>
5333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define ENABLE_DEBUG
5533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* #define ENABLE_VERBOSE */
5633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* #define ENABLE_TIMING */
5733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define BUFFER_SIZE 2048
5933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
6033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_DEBUG
61ae2da65e52e1720eb385135ea35552d5b5e4d9d1Steve Block#define DBG ALOGD
6233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#else
6333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define DBG(fmt, arg...)
6433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
6533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
6633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_VERBOSE
67999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block#define VDBG ALOGV
6833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#else
6933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define VDBG(fmt, arg...)
7033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
7133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
7233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifndef MIN
7333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh# define MIN(x, y) ((x) < (y) ? (x) : (y))
7433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
7533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
7633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifndef MAX
7733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh# define MAX(x, y) ((x) > (y) ? (x) : (y))
7833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
7933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define MAX_BITPOOL 64
8133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define MIN_BITPOOL 2
8233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
836934b76075fabbd7a1f542b3000b250f4a589492Steve Block#define ERR ALOGE
8433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* Number of packets to buffer in the stream socket */
8633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define PACKET_BUFFER_COUNT		10
8733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* timeout in milliseconds to prevent poll() from hanging indefinitely */
8933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define POLL_TIMEOUT			1000
9033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9114de1515561ce4627260bef13ec5677550e674c1Nick Pelly/* milliseconds of unsucessfull a2dp packets before we stop trying to catch up
9214de1515561ce4627260bef13ec5677550e674c1Nick Pelly * on write()'s and fall-back to metered writes */
9314de1515561ce4627260bef13ec5677550e674c1Nick Pelly#define CATCH_UP_TIMEOUT		200
9414de1515561ce4627260bef13ec5677550e674c1Nick Pelly
9533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* timeout in milliseconds for a2dp_write */
96722318b1247152c6ee282195f56efea4b0595e3cIan Kent#define WRITE_TIMEOUT			1000
9733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
985abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent/* timeout in seconds for command socket recv() */
99927aeb48a23a21c95f57ee990779fd529539873eEric Laurent#define RECV_TIMEOUT			5
1005abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent
10133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
10333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_NONE = 0,
10433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_INITIALIZED,
10533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURING,
10633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURED,
10733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTING,
10833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTED,
10933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STOPPING,
11033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_state_t;
11133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
11233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
11333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_NONE = 0,
11467bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh	A2DP_CMD_INIT,
11533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_CONFIGURE,
11633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_START,
11733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_STOP,
11833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_QUIT,
11933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_command_t;
12033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
12133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstruct bluetooth_data {
122c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	unsigned int link_mtu;			/* MTU for transport channel */
12333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd stream;			/* Audio stream filedescriptor */
12433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd server;			/* Audio daemon filedescriptor */
12533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state;				/* Current A2DP state */
12633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_command_t command;			/* Current command for a2dp_thread */
12733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_t thread;
12833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_t mutex;
1295bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	int started;
1305bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_t thread_start;
13133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t thread_wait;
13233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t client_wait;
13333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
13433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t sbc_capabilities;
13533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_t sbc;				/* Codec data */
13633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	frame_duration;			/* length of an SBC frame in microseconds */
13733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;				/* SBC codesize */
13833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int samples;				/* Number of encoded samples */
13933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
14033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int count;				/* Codec transfer buffer counter */
14133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int nsamples;				/* Cumulative number of codec samples */
14333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t seq_num;			/* Cumulative packet sequence */
14433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int frame_count;			/* Current frames in buffer*/
14533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char	address[20];
14733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	rate;
14833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	channels;
14933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* used for pacing our writes to the output socket */
15133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t	next_write;
15233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh};
15333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint64_t get_microseconds()
15533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
156e92f5a8ea09b2550c855964da37ceea5db372f5dNick Pelly	struct timespec now;
157e92f5a8ea09b2550c855964da37ceea5db372f5dNick Pelly	clock_gettime(CLOCK_MONOTONIC, &now);
158e92f5a8ea09b2550c855964da37ceea5db372f5dNick Pelly	return (now.tv_sec * 1000000UL + now.tv_nsec / 1000UL);
15933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
16033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
16133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
16233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void print_time(const char* message, uint64_t then, uint64_t now)
16333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
16433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("%s: %lld us", message, now - then);
16533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
16633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
16733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
16833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data, const bt_audio_msg_header_t *msg);
16933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data, bt_audio_msg_header_t *outmsg,
17033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				int expected_type);
17133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data);
17233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state);
17333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_close(struct bluetooth_data *data)
17633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
17733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_close");
17833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->server.fd >= 0) {
17933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_service_close(data->server.fd);
18033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->server.fd = -1;
18133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
18233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
18333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
18433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
18533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
18633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
18733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
18833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
18933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
19033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
19182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pellystatic int l2cap_set_flushable(int fd, int flushable)
19282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly{
19382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	int flags;
19482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	socklen_t len;
19582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
19682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	len = sizeof(flags);
19782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (getsockopt(fd, SOL_BLUETOOTH, BT_FLUSHABLE, &flags, &len) < 0)
19882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		return -errno;
19982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
20082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (flushable) {
20182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		if (flags == BT_FLUSHABLE_ON)
20282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly			return 0;
20382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		flags = BT_FLUSHABLE_ON;
20482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	} else {
20582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		if (flags == BT_FLUSHABLE_OFF)
20682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly			return 0;
20782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		flags = BT_FLUSHABLE_OFF;
20882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	}
20982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
21082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (setsockopt(fd, SOL_BLUETOOTH, L2CAP_LM, &flags, sizeof(flags)) < 0)
21182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		return -errno;
21282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
21382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	return 0;
21482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly}
21582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
21633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_start(struct bluetooth_data *data)
21733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
21833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char c = 'w';
21933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
22033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_req *start_req = (void*) buf;
22133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_rsp *start_rsp = (void*) buf;
22233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_new_stream_ind *streamfd_ind = (void*) buf;
22333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int opt_name, err, bytes;
22433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
22533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_start");
22633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STARTING;
22733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send start */
22833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(start_req, 0, BT_SUGGESTED_BUFFER_SIZE);
22974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.type = BT_REQUEST;
23074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.name = BT_START_STREAM;
23174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.length = sizeof(*start_req);
23233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &start_req->h);
23533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
23633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
23733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	start_rsp->h.length = sizeof(*start_rsp);
23933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &start_rsp->h, BT_START_STREAM);
24033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
24133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
24233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
24374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	streamfd_ind->h.length = sizeof(*streamfd_ind);
24433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &streamfd_ind->h, BT_NEW_STREAM);
24533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
24633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
24733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
24833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
24933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd < 0) {
25033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_get_data_fd failed, errno: %d", errno);
25133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
25233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
25333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
25482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	l2cap_set_flushable(data->stream.fd, 1);
25533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.events = POLLOUT;
25633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* set our socket buffer to the size of PACKET_BUFFER_COUNT packets */
25833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bytes = data->link_mtu * PACKET_BUFFER_COUNT;
25933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setsockopt(data->stream.fd, SOL_SOCKET, SO_SNDBUF, &bytes,
26033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			sizeof(bytes));
26133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
26233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
26333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
26433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
26533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->nsamples = 0;
26633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num = 0;
26733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
26833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->next_write = 0;
26933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
27033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_STARTED);
27133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
27233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
27333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
274927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	/* close bluetooth connection to force reinit and reconfiguration */
275007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson	if (data->state == A2DP_STATE_STARTING) {
276927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		bluetooth_close(data);
277007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson		/* notify client that thread is ready for next command */
278007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson		pthread_cond_signal(&data->client_wait);
279007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson        }
28033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
28133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
28233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
28333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_stop(struct bluetooth_data *data)
28433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
28533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
28633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_req *stop_req = (void*) buf;
28733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_rsp *stop_rsp = (void*) buf;
28833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
28933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
29033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_stop");
29133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
29233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STOPPING;
29382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	l2cap_set_flushable(data->stream.fd, 0);
29433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
29533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
29633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
29733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
29833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
29933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send stop request */
30033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(stop_req, 0, BT_SUGGESTED_BUFFER_SIZE);
30174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.type = BT_REQUEST;
30274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.name = BT_STOP_STREAM;
30374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.length = sizeof(*stop_req);
30433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
30533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &stop_req->h);
30633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
30733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
30833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
30933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	stop_rsp->h.length = sizeof(*stop_rsp);
31033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &stop_rsp->h, BT_STOP_STREAM);
31133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
31233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
31333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
31433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
31533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_STOPPING)
31633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_CONFIGURED);
31733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
31833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
31933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
32033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
32133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
32233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (freq) {
32333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_16000:
32433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_32000:
32533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
32633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_44100:
32733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
32833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
32933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
33033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 31;
33133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
33233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
33333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
33433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
33533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
33633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
33733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
33833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_48000:
33933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
34033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
34133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
34233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 29;
34333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
34433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
34533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
34633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
34733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
34833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
34933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
35033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
35133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Invalid sampling freq %u", freq);
35233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
35333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
35433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
35533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
35633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_init(struct bluetooth_data *data)
35733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
35833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t *cap = &data->sbc_capabilities;
35933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	unsigned int max_bitpool, min_bitpool;
36033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int dir;
36133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
36233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->rate) {
36333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 48000:
36433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
36533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
36633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 44100:
36733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
36833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
36933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 32000:
37033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
37133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
37233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 16000:
37333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
37433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
37533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
37633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Rate %d not supported", data->rate);
37733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
37833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
37933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
38033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->channels == 2) {
38133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
38233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
38333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
38433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
38533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
38633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
38733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
38833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
38933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
39033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
39133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!cap->channel_mode) {
39333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported channel modes");
39433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
39533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
39633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
39833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
39933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
40033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
40133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
40233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
40333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
40433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
40533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
40633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported block lengths");
40733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
40833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
40933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->subbands & BT_A2DP_SUBBANDS_8)
41133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_8;
41233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
41333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_4;
41433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
41533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported subbands");
41633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
41733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
41833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
42033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
42133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
42233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
42333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
42533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		max_bitpool = MIN(default_bitpool(cap->frequency,
42633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->channel_mode),
42733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->max_bitpool);
42833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->min_bitpool = min_bitpool;
43033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->max_bitpool = max_bitpool;
43133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
43333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
43433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_a2dp_setup(struct bluetooth_data *data)
43633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
43733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t active_capabilities = data->sbc_capabilities;
43833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_reinit(&data->sbc, 0);
44033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
44233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_16000;
44333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
44533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_32000;
44633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
44833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_44100;
44933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
45133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_48000;
45233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
45433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_MONO;
45533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
45733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_DUAL_CHANNEL;
45833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
46033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_STEREO;
46133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
46233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
46333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_JOINT_STEREO;
46433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
46533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.allocation = active_capabilities.allocation_method
46633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
46733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				: SBC_AM_LOUDNESS;
46833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
46933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.subbands) {
47033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_4:
47133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_4;
47233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
47333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_8:
47433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_8;
47533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
47633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
47733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
47833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.block_length) {
47933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_4:
48033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_4;
48133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
48233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_8:
48333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_8;
48433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
48533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_12:
48633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_12;
48733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
48833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_16:
48933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_16;
49033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
49133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
49233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
49333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.bitpool = active_capabilities.max_bitpool;
49433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->codesize = sbc_get_codesize(&data->sbc);
49533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_duration = sbc_get_frame_duration(&data->sbc);
49633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("frame_duration: %d us", data->frame_duration);
49733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
49833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
49933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data)
50033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
50133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
50233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_req *open_req = (void *) buf;
50333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_rsp *open_rsp = (void *) buf;
50433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_req *setconf_req = (void*) buf;
50533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_rsp *setconf_rsp = (void*) buf;
50633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
50733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
50874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memset(open_req, 0, BT_SUGGESTED_BUFFER_SIZE);
50933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.type = BT_REQUEST;
51033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.name = BT_OPEN;
51133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.length = sizeof(*open_req);
51233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(open_req->destination, data->address, 18);
51374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_req->seid = data->sbc_capabilities.capability.seid;
51433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->lock = BT_WRITE_LOCK;
51533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
51674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_send(data, &open_req->h);
51774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
51874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
51933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
52074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_rsp->h.length = sizeof(*open_rsp);
52174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_expect(data, &open_rsp->h, BT_OPEN);
52274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
52374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
52433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
52574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = bluetooth_a2dp_init(data);
52674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
52774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
52833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
52933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
53033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(setconf_req, 0, BT_SUGGESTED_BUFFER_SIZE);
53133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.type = BT_REQUEST;
53233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.name = BT_SET_CONFIGURATION;
53374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	setconf_req->h.length = sizeof(*setconf_req);
53474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&setconf_req->codec, &data->sbc_capabilities,
53574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						sizeof(data->sbc_capabilities));
53633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
53733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
53833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.length = sizeof(data->sbc_capabilities);
53933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.length += setconf_req->codec.length - sizeof(setconf_req->codec);
54033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
54133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_a2dp_hw_params sending configuration:\n");
54233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.channel_mode) {
54333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
54433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: MONO\n");
54533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
54733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: DUAL CHANNEL\n");
54833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
55033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: STEREO\n");
55133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
55333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: JOINT STEREO\n");
55433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
55633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: UNKNOWN (%d)\n",
55733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.channel_mode);
55833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
55933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.frequency) {
56033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_16000:
56133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 16000\n");
56233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_32000:
56433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 32000\n");
56533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_44100:
56733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 44100\n");
56833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_48000:
57033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 48000\n");
57133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
57233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
57333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: UNKNOWN (%d)\n",
57433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.frequency);
57533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
57633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.allocation_method) {
57733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_SNR:
57833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: SNR\n");
57933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
58033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_LOUDNESS:
58133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: LOUDNESS\n");
58233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
58333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
58433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: UNKNOWN (%d)\n",
58533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.allocation_method);
58633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
58733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.subbands) {
58833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_4:
58933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 4\n");
59033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
59133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_8:
59233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 8\n");
59333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
59433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
59533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: UNKNOWN (%d)\n",
59633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.subbands);
59733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
59833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.block_length) {
59933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_4:
60033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 4\n");
60133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
60233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_8:
60333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 8\n");
60433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
60533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_12:
60633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 12\n");
60733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
60833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_16:
60933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 16\n");
61033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
61133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
61233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: UNKNOWN (%d)\n",
61333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.block_length);
61433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
61533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmin_bitpool: %d\n", data->sbc_capabilities.min_bitpool);
61633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmax_bitpool: %d\n", data->sbc_capabilities.max_bitpool);
61733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &setconf_req->h);
61933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
62033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
62133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &setconf_rsp->h, BT_SET_CONFIGURATION);
62333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
62433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
62533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->link_mtu = setconf_rsp->link_mtu;
62733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("MTU: %d", data->link_mtu);
62833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Setup SBC encoder now we agree on parameters */
63033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_a2dp_setup(data);
63133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
63333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.allocation, data->sbc.subbands, data->sbc.blocks,
63433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.bitpool);
63533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
63733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
63833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int avdtp_write(struct bluetooth_data *data)
64033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
64133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int ret = 0;
64233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_header *header;
64333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_payload *payload;
64433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
64533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t now;
64633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long duration = data->frame_duration * data->frame_count;
64733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
64833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end, begin2, end2;
64933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
65033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
65133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header = (struct rtp_header *)data->buffer;
65333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload = (struct rtp_payload *)(data->buffer + sizeof(*header));
65433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data->buffer, 0, sizeof(*header) + sizeof(*payload));
65633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload->frame_count = data->frame_count;
65833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->v = 2;
65933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->pt = 1;
66033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->sequence_number = htons(data->seq_num);
66133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->timestamp = htonl(data->nsamples);
66233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->ssrc = htonl(1);
66333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
66433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.revents = 0;
66533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
66633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin2 = get_microseconds();
66733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
66833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = poll(&data->stream, 1, POLL_TIMEOUT);
66933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
67033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end2 = get_microseconds();
67133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("poll", begin2, end2);
67233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
67333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (ret == 1 && data->stream.revents == POLLOUT) {
67433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		long ahead = 0;
67533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		now = get_microseconds();
67633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
67733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (data->next_write) {
67833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ahead = data->next_write - now;
67933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
68033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("duration: %ld, ahead: %ld", duration, ahead);
68133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
68233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (ahead > 0) {
68333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				/* too fast, need to throttle */
68433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				usleep(ahead);
68533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			}
68633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		} else {
68733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			data->next_write = now;
68833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
68914de1515561ce4627260bef13ec5677550e674c1Nick Pelly		if (ahead <= -CATCH_UP_TIMEOUT * 1000) {
69014de1515561ce4627260bef13ec5677550e674c1Nick Pelly			/* fallen too far behind, don't try to catch up */
69114de1515561ce4627260bef13ec5677550e674c1Nick Pelly			VDBG("ahead < %d, reseting next_write timestamp", -CATCH_UP_TIMEOUT * 1000);
69214de1515561ce4627260bef13ec5677550e674c1Nick Pelly			data->next_write = 0;
69314de1515561ce4627260bef13ec5677550e674c1Nick Pelly		} else {
69414de1515561ce4627260bef13ec5677550e674c1Nick Pelly			data->next_write += duration;
69514de1515561ce4627260bef13ec5677550e674c1Nick Pelly		}
69633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
69733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
69833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		begin2 = get_microseconds();
69933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
70033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret = send(data->stream.fd, data->buffer, data->count, MSG_NOSIGNAL);
70133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
70233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		end2 = get_microseconds();
70333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		print_time("send", begin2, end2);
70433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
70533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret < 0) {
70633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			/* can happen during normal remote disconnect */
70733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("send() failed: %d (errno %s)", ret, strerror(errno));
70833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
70933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret == -EPIPE) {
71033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
71133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
71233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
71333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* can happen during normal remote disconnect */
71433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("poll() failed: %d (revents = %d, errno %s)",
71533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				ret, data->stream.revents, strerror(errno));
71614de1515561ce4627260bef13ec5677550e674c1Nick Pelly		data->next_write = 0;
71733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
71833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
71933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Reset buffer of data to send */
72033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
72133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
72233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
72333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num++;
72433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
72533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
72633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
72733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("avdtp_write", begin, end);
72833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
72933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0; /* always return success */
73033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
73133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
73233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data,
73333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		const bt_audio_msg_header_t *msg)
73433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
73533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
73633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t length;
73733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
73874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
73933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
740927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	VDBG("sending %s", bt_audio_strtype(msg->type));
74133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (send(data->server.fd, msg, length,
74233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			MSG_NOSIGNAL) > 0)
74333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = 0;
74433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
74533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
74633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Error sending data to audio service: %s(%d)",
74733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			strerror(errno), errno);
74833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
74933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
75033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
75133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
75233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
75333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
75433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
75533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_recv(struct bluetooth_data *data,
75633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *inmsg)
75733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
75833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret;
75933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *type, *name;
76074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	uint16_t length;
76133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
762104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
76333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
76433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = recv(data->server.fd, inmsg, length, 0);
76574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (ret < 0) {
76674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -errno;
76774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Error receiving IPC data from bluetoothd: %s (%d)",
76874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						strerror(errno), errno);
76933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
77033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
77174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
77274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
77374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
774104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	} else if (inmsg->type == BT_ERROR) {
775104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		bt_audio_error_t *error = (bt_audio_error_t *)inmsg;
776104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		ret = recv(data->server.fd, &error->posix_errno,
777104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				sizeof(error->posix_errno), 0);
778104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		if (ret < 0) {
779104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -errno;
780104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("Error receiving error code for BT_ERROR: %s (%d)",
781104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh						strerror(errno), errno);
782104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			if (err == -EPIPE)
783104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				bluetooth_close(data);
784104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		} else {
785104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("%s failed : %s(%d)",
786104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					bt_audio_strname(error->h.name),
787104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					strerror(error->posix_errno),
788104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					error->posix_errno);
789104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -error->posix_errno;
790104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		}
79174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else {
79274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		type = bt_audio_strtype(inmsg->type);
79374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		name = bt_audio_strname(inmsg->name);
79474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if (type && name) {
79574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			DBG("Received %s - %s", type, name);
79674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = 0;
79774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		} else {
79874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = -EINVAL;
79974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			ERR("Bogus message type %d - name %d"
80074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					" received from audio service",
80174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					inmsg->type, inmsg->name);
80274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		}
80374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
80474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
80533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
80633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
80733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
80833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data,
80933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *rsp_hdr, int expected_name)
81033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
81174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int err = audioservice_recv(data, rsp_hdr);
81274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
81374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err != 0)
81474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
81574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
81674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (rsp_hdr->name != expected_name) {
81774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
81874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Bogus message %s received while %s was expected",
81974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(rsp_hdr->name),
82074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(expected_name));
82174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
82274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return err;
82333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
82433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
82533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
82633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_init(struct bluetooth_data *data)
82733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
82833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int sk, err;
829927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	struct timeval tv = {.tv_sec = RECV_TIMEOUT};
83033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_init");
83233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sk = bt_audio_service_open();
834927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	if (sk < 0) {
83533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_open failed\n");
83633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -errno;
83733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
83833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
839927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	err = setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
840927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	if (err < 0) {
841927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		ERR("bluetooth_init setsockopt(SO_RCVTIMEO) failed %d", err);
842927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		return err;
843927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	}
8445abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent
84533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = sk;
84633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.events = POLLIN;
84733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_INITIALIZED;
84833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
85033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
85133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
85374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					struct bt_get_capabilities_rsp *rsp)
85433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
85574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int bytes_left = rsp->h.length - sizeof(*rsp);
85674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	codec_capabilities_t *codec = (void *) rsp->data;
85733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
859927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		return -EINVAL;
86033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
86174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	while (bytes_left > 0) {
86274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if ((codec->type == BT_A2DP_SBC_SINK) &&
863927aeb48a23a21c95f57ee990779fd529539873eEric Laurent			!(codec->lock & BT_WRITE_LOCK))
86474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			break;
86533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
866927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		if (codec->length == 0) {
867927aeb48a23a21c95f57ee990779fd529539873eEric Laurent			ERR("bluetooth_parse_capabilities() invalid codec capabilities length");
868927aeb48a23a21c95f57ee990779fd529539873eEric Laurent			return -EINVAL;
869927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		}
87074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		bytes_left -= codec->length;
871927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		codec = (codec_capabilities_t *)((char *)codec + codec->length);
87274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
87333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (bytes_left <= 0 ||
87574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			codec->length != sizeof(data->sbc_capabilities))
87674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return -EINVAL;
87733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&data->sbc_capabilities, codec, codec->length);
87974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return 0;
88033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
88133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_configure(struct bluetooth_data *data)
88433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
88533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
88633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_req *getcaps_req = (void*) buf;
88733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_rsp *getcaps_rsp = (void*) buf;
88833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
88933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
89033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_configure");
89133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
89233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_CONFIGURING;
89333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(getcaps_req, 0, BT_SUGGESTED_BUFFER_SIZE);
89433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.type = BT_REQUEST;
89533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.name = BT_GET_CAPABILITIES;
89633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
89733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags = 0;
89833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
89933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(getcaps_req->destination, data->address, 18);
90033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
90133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.length = sizeof(*getcaps_req);
90233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
90333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &getcaps_req->h);
90433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
90533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_send failed for BT_GETCAPABILITIES_REQ\n");
90633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
90733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
90833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
90933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_rsp->h.length = 0;
91033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &getcaps_rsp->h, BT_GET_CAPABILITIES);
91133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
91233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_expect failed for BT_GETCAPABILITIES_RSP\n");
91333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
91433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
91533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
916927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	err = bluetooth_parse_capabilities(data, getcaps_rsp);
917927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	if (err < 0) {
918927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		ERR("bluetooth_parse_capabilities failed err: %d", err);
919927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		goto error;
920927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	}
921927aeb48a23a21c95f57ee990779fd529539873eEric Laurent
92233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = bluetooth_a2dp_hw_params(data);
92333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
92433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bluetooth_a2dp_hw_params failed err: %d", err);
92533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
92633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
92733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
928927aeb48a23a21c95f57ee990779fd529539873eEric Laurent
92933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_CONFIGURED);
93033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
93133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
93233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
933927aeb48a23a21c95f57ee990779fd529539873eEric Laurent
934007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson	if (data->state == A2DP_STATE_CONFIGURING) {
935927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		bluetooth_close(data);
936007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson		/* notify client that thread is ready for next command */
937007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson		pthread_cond_signal(&data->client_wait);
938007af38ddeb22f02663a2d879634642b61457634Mathias Jeppsson        }
93933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
94033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
94133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
94233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state)
94333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
94433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = state;
94533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->client_wait);
94633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
94733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
94871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kentstatic void __set_command(struct bluetooth_data *data, a2dp_command_t command)
94933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
95033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	VDBG("set_command %d\n", command);
95133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->command = command;
95233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->thread_wait);
95371d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	return;
95471d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent}
95571d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent
95671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kentstatic void set_command(struct bluetooth_data *data, a2dp_command_t command)
95771d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent{
95871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_lock(&data->mutex);
95971d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	__set_command(data, command);
96033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_unlock(&data->mutex);
96133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
96233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9639ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood/* timeout is in milliseconds */
96433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int wait_for_start(struct bluetooth_data *data, int timeout)
96533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
96633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state = data->state;
9679ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	struct timeval tv;
96833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct timespec ts;
96933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err = 0;
97033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9719ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#ifdef ENABLE_TIMING
9729ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	uint64_t begin, end;
97333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
9749ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#endif
9759ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood
9769ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	gettimeofday(&tv, (struct timezone *) NULL);
9779ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_sec = tv.tv_sec + (timeout / 1000);
9789ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000L ) * 1000L;
97933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
98071d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_lock(&data->mutex);
981b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent	while (state != A2DP_STATE_STARTED) {
98233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (state == A2DP_STATE_NONE)
9835abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent			__set_command(data, A2DP_CMD_INIT);
98433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (state == A2DP_STATE_INITIALIZED)
98571d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			__set_command(data, A2DP_CMD_CONFIGURE);
98671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		else if (state == A2DP_STATE_CONFIGURED) {
98771d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			__set_command(data, A2DP_CMD_START);
98871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		}
989b259b11bf5ac5259069d1144cd049e213352ed74Ian Kentagain:
990b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts);
991b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		if (err) {
992b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			/* don't timeout if we're done */
993b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			if (data->state == A2DP_STATE_STARTED) {
994b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				err = 0;
995b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				break;
996b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			}
997b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			if (err == ETIMEDOUT)
998b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				break;
999b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			goto again;
1000b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		}
1001b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent
1002b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		if (state == data->state)
1003b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			goto again;
100433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
100533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		state = data->state;
100671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent
100771d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		if (state == A2DP_STATE_NONE) {
100871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			err = ENODEV;
100971d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			break;
101071d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		}
101133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
101271d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_unlock(&data->mutex);
101333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
101433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
101533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
101633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("wait_for_start", begin, end);
101733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
101833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
101933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* pthread_cond_timedwait returns positive errors */
102033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return -err;
102133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
102233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
1023be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kentstatic void a2dp_free(struct bluetooth_data *data)
1024be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent{
1025be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->client_wait);
1026be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->thread_wait);
1027be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->thread_start);
1028be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_mutex_destroy(&data->mutex);
1029be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	free(data);
1030be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	return;
1031be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent}
1032be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent
103333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void* a2dp_thread(void *d)
103433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
103533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
10366782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	a2dp_command_t command = A2DP_CMD_NONE;
1037927aeb48a23a21c95f57ee990779fd529539873eEric Laurent	int err = 0;
103833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
103933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread started");
1040c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	prctl(PR_SET_NAME, (int)"a2dp_thread", 0, 0, 0);
104133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
1042281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_lock(&data->mutex);
1043281c324f0ba38b0720884b53d465b1420fac616aIan Kent
1044281c324f0ba38b0720884b53d465b1420fac616aIan Kent	data->started = 1;
1045281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_start);
1046281c324f0ba38b0720884b53d465b1420fac616aIan Kent
104733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (1)
104833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	{
10496782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		while (1) {
10506782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			pthread_cond_wait(&data->thread_wait, &data->mutex);
105133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10526782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* Initialization needed */
10536782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (data->state == A2DP_STATE_NONE &&
1054927aeb48a23a21c95f57ee990779fd529539873eEric Laurent				data->command != A2DP_CMD_QUIT) {
1055927aeb48a23a21c95f57ee990779fd529539873eEric Laurent				err = bluetooth_init(data);
10566782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
10576782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent
10586782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* New state command signaled */
10596782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (command != data->command) {
10606782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				command = data->command;
10616782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				break;
10626782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
10636782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		}
106433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
106533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (command) {
106633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_CONFIGURE:
106733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_INITIALIZED)
106833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
1069927aeb48a23a21c95f57ee990779fd529539873eEric Laurent				err = bluetooth_configure(data);
107033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
107133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
107233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_START:
107333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_CONFIGURED)
107433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
1075927aeb48a23a21c95f57ee990779fd529539873eEric Laurent				err = bluetooth_start(data);
107633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
107733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
107833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_STOP:
107933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_STARTED)
108033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
1081927aeb48a23a21c95f57ee990779fd529539873eEric Laurent				err = bluetooth_stop(data);
108233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
108333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
108433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_QUIT:
108533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_close(data);
108633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				sbc_finish(&data->sbc);
1087be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent				a2dp_free(data);
108833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				goto done;
108933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
1090533b9f6e793e4c7aa09e7127077d8e9a2d388504Nick Pelly			case A2DP_CMD_INIT:
1091533b9f6e793e4c7aa09e7127077d8e9a2d388504Nick Pelly				/* already called bluetooth_init() */
109233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			default:
109333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
109433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
1095927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		// reset last command in case of error to allow
1096927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		// re-execution of the same command
1097927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		if (err < 0) {
1098927aeb48a23a21c95f57ee990779fd529539873eEric Laurent			command = A2DP_CMD_NONE;
1099927aeb48a23a21c95f57ee990779fd529539873eEric Laurent		}
110033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
110133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
110233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
1103281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_unlock(&data->mutex);
110433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread finished");
110533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return NULL;
110633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
110733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
110833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_init(int rate, int channels, a2dpData* dataPtr)
110933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
111033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data;
111133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_t attr;
111233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
111333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
111433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_init rate: %d channels: %d", rate, channels);
111533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = NULL;
111633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data = malloc(sizeof(struct bluetooth_data));
111733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
111833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
111933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
112033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data, 0, sizeof(struct bluetooth_data));
112133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = -1;
112233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = -1;
112333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
11246782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	data->command = A2DP_CMD_NONE;
112533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
112633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(data->address, "00:00:00:00:00:00", 18);
112733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->rate = rate;
112833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->channels = channels;
112933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_init(&data->sbc, 0);
113133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_init(&data->mutex, NULL);
11335bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_init(&data->thread_start, NULL);
113433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->thread_wait, NULL);
113533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->client_wait, NULL);
113633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
11375bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_lock(&data->mutex);
11385bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	data->started = 0;
11395bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
114033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_init(&attr);
114133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11425bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
11435bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	err = pthread_create(&data->thread, &attr, a2dp_thread, data);
11445bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	if (err) {
11455bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		/* If the thread create fails we must not wait */
11465bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_mutex_unlock(&data->mutex);
11475bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		err = -err;
11485bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		goto error;
11495bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
11505bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1151281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Make sure the state machine is ready and waiting */
11525bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	while (!data->started) {
11535bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_cond_wait(&data->thread_start, &data->mutex);
11545bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
11555bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1156281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Poke the state machine to get it going */
1157281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_wait);
1158281c324f0ba38b0720884b53d465b1420fac616aIan Kent
11595bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_unlock(&data->mutex);
11603da4d6ad9402b574ee4dc7923f1d27b1fa2302a0Ian Kent	pthread_attr_destroy(&attr);
116133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
116233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = data;
116333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
116433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
116533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_close(data);
11665bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	sbc_finish(&data->sbc);
11673da4d6ad9402b574ee4dc7923f1d27b1fa2302a0Ian Kent	pthread_attr_destroy(&attr);
1168be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	a2dp_free(data);
116933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
117033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
117133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
117233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
117333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_set_sink(a2dpData d, const char* address)
117433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
117533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
117633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (strncmp(data->address, address, 18)) {
117733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		strncpy(data->address, address, 18);
117867bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh		set_command(data, A2DP_CMD_INIT);
117933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
118033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
118133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
118233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_write(a2dpData d, const void* buffer, int count)
118333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
118433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
118533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t* src = (uint8_t *)buffer;
118633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;
118733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret = 0;
118833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long frames_left = count;
1189c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	int encoded;
1190c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	unsigned int written;
119133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *buff;
119233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int did_configure = 0;
119333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
119433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end;
119533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("********** a2dp_write **********");
119633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
119733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
119833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
119933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = wait_for_start(data, WRITE_TIMEOUT);
120033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
120133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
120233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
120333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	codesize = data->codesize;
120433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
120533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (frames_left >= codesize) {
120633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* Enough data to encode (sbc wants 512 byte blocks) */
120733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		encoded = sbc_encode(&(data->sbc), src, codesize,
120833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->buffer + data->count,
120933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					sizeof(data->buffer) - data->count,
121033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					&written);
121133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (encoded <= 0) {
121233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Encoding error %d", encoded);
121333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			goto done;
121433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
121533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("sbc_encode returned %d, codesize: %d, written: %d\n",
121633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			encoded, codesize, written);
121733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
121833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		src += encoded;
121933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->count += written;
122033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->frame_count++;
122133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->samples += encoded;
122233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->nsamples += encoded;
122333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
122433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* No space left for another frame then send */
12259d60b87413f23ef48d3cb24bb44f51745c02a332Yu Kang Ku		if ((data->count + written >= data->link_mtu) ||
12269d60b87413f23ef48d3cb24bb44f51745c02a332Yu Kang Ku				(data->count + written >= BUFFER_SIZE)) {
122733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("sending packet %d, count %d, link_mtu %u",
122833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->seq_num, data->count,
122933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->link_mtu);
123033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			err = avdtp_write(data);
123133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (err < 0)
123233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				return err;
123333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
123433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
123533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret += encoded;
123633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		frames_left -= encoded;
123733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
123833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
123933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (frames_left > 0)
124033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("%ld bytes left at end of a2dp_write\n", frames_left);
124133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
124233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
124333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
124433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
124533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("a2dp_write total", begin, end);
124633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
124733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return ret;
124833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
124933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
125033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_stop(a2dpData d)
125133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
125233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
125333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_stop\n");
125433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
125533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 0;
125633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
125733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_STOP);
125833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
125933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
126033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
126133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_cleanup(a2dpData d)
126233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
126333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
126433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_cleanup\n");
126533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_QUIT);
126633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
1267