liba2dp.c revision c4e47c15ae8fe36673e7cdd7ee3caaffddb5071e
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
6133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define DBG LOGD
6233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#else
6333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define DBG(fmt, arg...)
6433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
6533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
6633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_VERBOSE
6733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define VDBG LOGV
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
8333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define ERR LOGE
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
9133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* timeout in milliseconds for a2dp_write */
92722318b1247152c6ee282195f56efea4b0595e3cIan Kent#define WRITE_TIMEOUT			1000
9333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
945abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent/* timeout in seconds for command socket recv() */
955abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent#define RECV_TIMEOUT            5
965abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent
9733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
9933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_NONE = 0,
10033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_INITIALIZED,
10133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURING,
10233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURED,
10333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTING,
10433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTED,
10533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STOPPING,
10633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_state_t;
10733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
10933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_NONE = 0,
11067bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh	A2DP_CMD_INIT,
11133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_CONFIGURE,
11233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_START,
11333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_STOP,
11433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_QUIT,
11533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_command_t;
11633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
11733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstruct bluetooth_data {
118c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	unsigned int link_mtu;			/* MTU for transport channel */
11933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd stream;			/* Audio stream filedescriptor */
12033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd server;			/* Audio daemon filedescriptor */
12133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state;				/* Current A2DP state */
12233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_command_t command;			/* Current command for a2dp_thread */
12333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_t thread;
12433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_t mutex;
1255bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	int started;
1265bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_t thread_start;
12733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t thread_wait;
12833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t client_wait;
12933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
13033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t sbc_capabilities;
13133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_t sbc;				/* Codec data */
13233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	frame_duration;			/* length of an SBC frame in microseconds */
13333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;				/* SBC codesize */
13433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int samples;				/* Number of encoded samples */
13533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
13633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int count;				/* Codec transfer buffer counter */
13733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
13833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int nsamples;				/* Cumulative number of codec samples */
13933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t seq_num;			/* Cumulative packet sequence */
14033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int frame_count;			/* Current frames in buffer*/
14133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char	address[20];
14333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	rate;
14433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	channels;
14533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* used for pacing our writes to the output socket */
14733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t	next_write;
14833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh};
14933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint64_t get_microseconds()
15133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
15233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct timeval now;
15333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	gettimeofday(&now, NULL);
15433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return (now.tv_sec * 1000000UL + now.tv_usec);
15533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
15633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
15833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void print_time(const char* message, uint64_t then, uint64_t now)
15933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
16033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("%s: %lld us", message, now - then);
16133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
16233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
16333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
16433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data, const bt_audio_msg_header_t *msg);
16533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data, bt_audio_msg_header_t *outmsg,
16633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				int expected_type);
16733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data);
16833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state);
16933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_close(struct bluetooth_data *data)
17233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
17333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_close");
17433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->server.fd >= 0) {
17533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_service_close(data->server.fd);
17633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->server.fd = -1;
17733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
17833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
18033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
18133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
18233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
18333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
18433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
18533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
18633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
18782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pellystatic int l2cap_set_flushable(int fd, int flushable)
18882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly{
18982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	int flags;
19082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	socklen_t len;
19182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
19282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	len = sizeof(flags);
19382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (getsockopt(fd, SOL_BLUETOOTH, BT_FLUSHABLE, &flags, &len) < 0)
19482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		return -errno;
19582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
19682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (flushable) {
19782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		if (flags == BT_FLUSHABLE_ON)
19882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly			return 0;
19982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		flags = BT_FLUSHABLE_ON;
20082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	} else {
20182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		if (flags == BT_FLUSHABLE_OFF)
20282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly			return 0;
20382c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		flags = BT_FLUSHABLE_OFF;
20482c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	}
20582c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
20682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	if (setsockopt(fd, SOL_BLUETOOTH, L2CAP_LM, &flags, sizeof(flags)) < 0)
20782c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		return -errno;
20882c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
20982c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	return 0;
21082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly}
21182c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly
21233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_start(struct bluetooth_data *data)
21333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
21433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char c = 'w';
21533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
21633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_req *start_req = (void*) buf;
21733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_rsp *start_rsp = (void*) buf;
21833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_new_stream_ind *streamfd_ind = (void*) buf;
21933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int opt_name, err, bytes;
22033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
22133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_start");
22233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STARTING;
22333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send start */
22433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(start_req, 0, BT_SUGGESTED_BUFFER_SIZE);
22574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.type = BT_REQUEST;
22674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.name = BT_START_STREAM;
22774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.length = sizeof(*start_req);
22833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
22933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &start_req->h);
23133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
23233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
23333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	start_rsp->h.length = sizeof(*start_rsp);
23533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &start_rsp->h, BT_START_STREAM);
23633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
23733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
23833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	streamfd_ind->h.length = sizeof(*streamfd_ind);
24033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &streamfd_ind->h, BT_NEW_STREAM);
24133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
24233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
24333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
24433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
24533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd < 0) {
24633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_get_data_fd failed, errno: %d", errno);
24733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
24833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
24933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
25082c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	l2cap_set_flushable(data->stream.fd, 1);
25133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.events = POLLOUT;
25233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* set our socket buffer to the size of PACKET_BUFFER_COUNT packets */
25433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bytes = data->link_mtu * PACKET_BUFFER_COUNT;
25533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setsockopt(data->stream.fd, SOL_SOCKET, SO_SNDBUF, &bytes,
25633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			sizeof(bytes));
25733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
25933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
26033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
26133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->nsamples = 0;
26233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num = 0;
26333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
26433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->next_write = 0;
26533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
26633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_STARTED);
26733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
26833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
26933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
27033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* set state to A2DP_STATE_INITIALIZED to force reconfiguration */
27133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_STARTING)
27233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_INITIALIZED);
27333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
27433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
27533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
27633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_stop(struct bluetooth_data *data)
27733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
27833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
27933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_req *stop_req = (void*) buf;
28033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_rsp *stop_rsp = (void*) buf;
28133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
28233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
28333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_stop");
28433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
28533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STOPPING;
28682c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly	l2cap_set_flushable(data->stream.fd, 0);
28733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
28833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
28933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
29033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
29133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
29233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send stop request */
29333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(stop_req, 0, BT_SUGGESTED_BUFFER_SIZE);
29474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.type = BT_REQUEST;
29574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.name = BT_STOP_STREAM;
29674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.length = sizeof(*stop_req);
29733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
29833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &stop_req->h);
29933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
30033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
30133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
30233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	stop_rsp->h.length = sizeof(*stop_rsp);
30333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &stop_rsp->h, BT_STOP_STREAM);
30433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
30533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
30633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
30733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
30833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_STOPPING)
30933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_CONFIGURED);
31033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
31133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
31233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
31333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
31433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
31533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (freq) {
31633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_16000:
31733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_32000:
31833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
31933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_44100:
32033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
32133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
32233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
32333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 31;
32433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
32533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
32633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
32733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
32833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
32933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
33033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
33133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_48000:
33233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
33333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
33433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
33533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 29;
33633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
33733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
33833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
33933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
34033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
34133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
34233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
34333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
34433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Invalid sampling freq %u", freq);
34533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
34633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
34733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
34833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
34933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_init(struct bluetooth_data *data)
35033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
35133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t *cap = &data->sbc_capabilities;
35233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	unsigned int max_bitpool, min_bitpool;
35333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int dir;
35433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
35533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->rate) {
35633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 48000:
35733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
35833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
35933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 44100:
36033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
36133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
36233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 32000:
36333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
36433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
36533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 16000:
36633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
36733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
36833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
36933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Rate %d not supported", data->rate);
37033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
37133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
37233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
37333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->channels == 2) {
37433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
37533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
37633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
37733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
37833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
37933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
38033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
38133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
38233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
38333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
38433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
38533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!cap->channel_mode) {
38633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported channel modes");
38733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
38833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
38933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
39133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
39233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
39333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
39433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
39533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
39633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
39733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
39833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
39933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported block lengths");
40033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
40133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
40233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
40333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->subbands & BT_A2DP_SUBBANDS_8)
40433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_8;
40533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
40633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_4;
40733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
40833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported subbands");
40933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
41033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
41133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
41333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
41433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
41533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
41633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
41833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		max_bitpool = MIN(default_bitpool(cap->frequency,
41933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->channel_mode),
42033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->max_bitpool);
42133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->min_bitpool = min_bitpool;
42333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->max_bitpool = max_bitpool;
42433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
42633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
42733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_a2dp_setup(struct bluetooth_data *data)
42933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
43033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t active_capabilities = data->sbc_capabilities;
43133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_reinit(&data->sbc, 0);
43333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
43533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_16000;
43633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
43833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_32000;
43933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
44133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_44100;
44233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
44433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_48000;
44533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
44733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_MONO;
44833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
44933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
45033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_DUAL_CHANNEL;
45133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
45333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_STEREO;
45433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
45633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_JOINT_STEREO;
45733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.allocation = active_capabilities.allocation_method
45933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
46033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				: SBC_AM_LOUDNESS;
46133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
46233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.subbands) {
46333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_4:
46433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_4;
46533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
46633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_8:
46733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_8;
46833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
46933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
47033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
47133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.block_length) {
47233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_4:
47333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_4;
47433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
47533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_8:
47633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_8;
47733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
47833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_12:
47933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_12;
48033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
48133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_16:
48233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_16;
48333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
48433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
48533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
48633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.bitpool = active_capabilities.max_bitpool;
48733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->codesize = sbc_get_codesize(&data->sbc);
48833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_duration = sbc_get_frame_duration(&data->sbc);
48933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("frame_duration: %d us", data->frame_duration);
49033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
49133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
49233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data)
49333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
49433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
49533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_req *open_req = (void *) buf;
49633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_rsp *open_rsp = (void *) buf;
49733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_req *setconf_req = (void*) buf;
49833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_rsp *setconf_rsp = (void*) buf;
49933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
50033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
50174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memset(open_req, 0, BT_SUGGESTED_BUFFER_SIZE);
50233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.type = BT_REQUEST;
50333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.name = BT_OPEN;
50433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.length = sizeof(*open_req);
50533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(open_req->destination, data->address, 18);
50674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_req->seid = data->sbc_capabilities.capability.seid;
50733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->lock = BT_WRITE_LOCK;
50833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
50974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_send(data, &open_req->h);
51074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
51174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
51233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
51374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_rsp->h.length = sizeof(*open_rsp);
51474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_expect(data, &open_rsp->h, BT_OPEN);
51574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
51674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
51733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
51874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = bluetooth_a2dp_init(data);
51974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
52074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
52133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
52233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
52333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(setconf_req, 0, BT_SUGGESTED_BUFFER_SIZE);
52433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.type = BT_REQUEST;
52533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.name = BT_SET_CONFIGURATION;
52674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	setconf_req->h.length = sizeof(*setconf_req);
52774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&setconf_req->codec, &data->sbc_capabilities,
52874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						sizeof(data->sbc_capabilities));
52933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
53033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
53133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.length = sizeof(data->sbc_capabilities);
53233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.length += setconf_req->codec.length - sizeof(setconf_req->codec);
53333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
53433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_a2dp_hw_params sending configuration:\n");
53533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.channel_mode) {
53633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
53733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: MONO\n");
53833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
53933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
54033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: DUAL CHANNEL\n");
54133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
54333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: STEREO\n");
54433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
54633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: JOINT STEREO\n");
54733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
54933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: UNKNOWN (%d)\n",
55033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.channel_mode);
55133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
55233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.frequency) {
55333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_16000:
55433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 16000\n");
55533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_32000:
55733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 32000\n");
55833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_44100:
56033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 44100\n");
56133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_48000:
56333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 48000\n");
56433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
56633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: UNKNOWN (%d)\n",
56733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.frequency);
56833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
56933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.allocation_method) {
57033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_SNR:
57133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: SNR\n");
57233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
57333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_LOUDNESS:
57433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: LOUDNESS\n");
57533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
57633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
57733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: UNKNOWN (%d)\n",
57833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.allocation_method);
57933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
58033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.subbands) {
58133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_4:
58233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 4\n");
58333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
58433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_8:
58533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 8\n");
58633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
58733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
58833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: UNKNOWN (%d)\n",
58933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.subbands);
59033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
59133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.block_length) {
59233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_4:
59333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 4\n");
59433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
59533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_8:
59633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 8\n");
59733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
59833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_12:
59933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 12\n");
60033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
60133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_16:
60233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 16\n");
60333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
60433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
60533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: UNKNOWN (%d)\n",
60633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.block_length);
60733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
60833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmin_bitpool: %d\n", data->sbc_capabilities.min_bitpool);
60933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmax_bitpool: %d\n", data->sbc_capabilities.max_bitpool);
61033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &setconf_req->h);
61233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
61333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
61433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &setconf_rsp->h, BT_SET_CONFIGURATION);
61633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
61733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
61833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->link_mtu = setconf_rsp->link_mtu;
62033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("MTU: %d", data->link_mtu);
62133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Setup SBC encoder now we agree on parameters */
62333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_a2dp_setup(data);
62433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
62633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.allocation, data->sbc.subbands, data->sbc.blocks,
62733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.bitpool);
62833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
63033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
63133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int avdtp_write(struct bluetooth_data *data)
63333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
63433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int ret = 0;
63533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_header *header;
63633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_payload *payload;
63733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t now;
63933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long duration = data->frame_duration * data->frame_count;
64033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
64133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end, begin2, end2;
64233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
64333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
64433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
64533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header = (struct rtp_header *)data->buffer;
64633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload = (struct rtp_payload *)(data->buffer + sizeof(*header));
64733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
64833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data->buffer, 0, sizeof(*header) + sizeof(*payload));
64933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload->frame_count = data->frame_count;
65133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->v = 2;
65233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->pt = 1;
65333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->sequence_number = htons(data->seq_num);
65433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->timestamp = htonl(data->nsamples);
65533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->ssrc = htonl(1);
65633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.revents = 0;
65833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
65933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin2 = get_microseconds();
66033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
66133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = poll(&data->stream, 1, POLL_TIMEOUT);
66233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
66333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end2 = get_microseconds();
66433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("poll", begin2, end2);
66533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
66633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (ret == 1 && data->stream.revents == POLLOUT) {
66733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		long ahead = 0;
66833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		now = get_microseconds();
66933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
67033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (data->next_write) {
67133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ahead = data->next_write - now;
67233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
67333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("duration: %ld, ahead: %ld", duration, ahead);
67433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
67533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (ahead > 0) {
67633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				/* too fast, need to throttle */
67733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				usleep(ahead);
67833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			}
67933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		} else {
68033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			data->next_write = now;
68133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
68282c2b608fb43d741bfc4733a9c3d310c89b01e87Nick Pelly		data->next_write += duration;
68333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
68433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
68533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		begin2 = get_microseconds();
68633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
68733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret = send(data->stream.fd, data->buffer, data->count, MSG_NOSIGNAL);
68833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
68933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		end2 = get_microseconds();
69033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		print_time("send", begin2, end2);
69133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
69233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret < 0) {
69333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			/* can happen during normal remote disconnect */
69433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("send() failed: %d (errno %s)", ret, strerror(errno));
69533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
69633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret == -EPIPE) {
69733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
69833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
69933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
70033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* can happen during normal remote disconnect */
70133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("poll() failed: %d (revents = %d, errno %s)",
70233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				ret, data->stream.revents, strerror(errno));
70333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
70433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
70533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Reset buffer of data to send */
70633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
70733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
70833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
70933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num++;
71033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
71133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
71233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
71333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("avdtp_write", begin, end);
71433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
71533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0; /* always return success */
71633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
71733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
71833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data,
71933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		const bt_audio_msg_header_t *msg)
72033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
72133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
72233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t length;
72333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
72474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
72533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
72633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	VDBG("sending %s", bt_audio_strmsg(msg->msg_type));
72733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (send(data->server.fd, msg, length,
72833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			MSG_NOSIGNAL) > 0)
72933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = 0;
73033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
73133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
73233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Error sending data to audio service: %s(%d)",
73333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			strerror(errno), errno);
73433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
73533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
73633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
73733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
73833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
73933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
74033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
74133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_recv(struct bluetooth_data *data,
74233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *inmsg)
74333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
74433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret;
74533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *type, *name;
74674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	uint16_t length;
74733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
748104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
74933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
75033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = recv(data->server.fd, inmsg, length, 0);
75174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (ret < 0) {
75274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -errno;
75374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Error receiving IPC data from bluetoothd: %s (%d)",
75474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						strerror(errno), errno);
75533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
75633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
75774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
75874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
75974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
760104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	} else if (inmsg->type == BT_ERROR) {
761104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		bt_audio_error_t *error = (bt_audio_error_t *)inmsg;
762104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		ret = recv(data->server.fd, &error->posix_errno,
763104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				sizeof(error->posix_errno), 0);
764104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		if (ret < 0) {
765104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -errno;
766104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("Error receiving error code for BT_ERROR: %s (%d)",
767104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh						strerror(errno), errno);
768104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			if (err == -EPIPE)
769104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				bluetooth_close(data);
770104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		} else {
771104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("%s failed : %s(%d)",
772104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					bt_audio_strname(error->h.name),
773104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					strerror(error->posix_errno),
774104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					error->posix_errno);
775104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -error->posix_errno;
776104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		}
77774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else {
77874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		type = bt_audio_strtype(inmsg->type);
77974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		name = bt_audio_strname(inmsg->name);
78074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if (type && name) {
78174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			DBG("Received %s - %s", type, name);
78274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = 0;
78374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		} else {
78474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = -EINVAL;
78574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			ERR("Bogus message type %d - name %d"
78674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					" received from audio service",
78774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					inmsg->type, inmsg->name);
78874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		}
78974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
79074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
79133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
79233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
79333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
79433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data,
79533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *rsp_hdr, int expected_name)
79633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
79774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int err = audioservice_recv(data, rsp_hdr);
79874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
79974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err != 0)
80074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
80174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
80274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (rsp_hdr->name != expected_name) {
80374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
80474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Bogus message %s received while %s was expected",
80574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(rsp_hdr->name),
80674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(expected_name));
80774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
80874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return err;
80933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
81133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_init(struct bluetooth_data *data)
81333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
81433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int sk, err;
8155abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent        struct timeval tv = {.tv_sec = RECV_TIMEOUT};
81633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_init");
81833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sk = bt_audio_service_open();
82033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (sk <= 0) {
82133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_open failed\n");
82233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -errno;
82333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
82433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8255abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent        setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
8265abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent
82733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = sk;
82833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.events = POLLIN;
82933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_INITIALIZED;
83033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
83233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
83333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
83574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					struct bt_get_capabilities_rsp *rsp)
83633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
83774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int bytes_left = rsp->h.length - sizeof(*rsp);
83874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	codec_capabilities_t *codec = (void *) rsp->data;
83933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
84174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return 0;
84233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	while (bytes_left > 0) {
84474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if ((codec->type == BT_A2DP_SBC_SINK) &&
84574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				!(codec->lock & BT_WRITE_LOCK))
84674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			break;
84733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		bytes_left -= codec->length;
849c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly		codec = (void *) (codec + codec->length);
85074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
85133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (bytes_left <= 0 ||
85374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			codec->length != sizeof(data->sbc_capabilities))
85474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return -EINVAL;
85533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&data->sbc_capabilities, codec, codec->length);
85774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return 0;
85833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
85933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
86033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
86133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_configure(struct bluetooth_data *data)
86233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
86333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
86433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_req *getcaps_req = (void*) buf;
86533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_rsp *getcaps_rsp = (void*) buf;
86633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
86733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
86833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_configure");
86933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_CONFIGURING;
87133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(getcaps_req, 0, BT_SUGGESTED_BUFFER_SIZE);
87233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.type = BT_REQUEST;
87333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.name = BT_GET_CAPABILITIES;
87433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags = 0;
87633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
87733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(getcaps_req->destination, data->address, 18);
87833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
87933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.length = sizeof(*getcaps_req);
88033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &getcaps_req->h);
88233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
88333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_send failed for BT_GETCAPABILITIES_REQ\n");
88433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
88533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
88633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_rsp->h.length = 0;
88833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &getcaps_rsp->h, BT_GET_CAPABILITIES);
88933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
89033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_expect failed for BT_GETCAPABILITIES_RSP\n");
89133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
89233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
89333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
89433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_parse_capabilities(data, getcaps_rsp);
89533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = bluetooth_a2dp_hw_params(data);
89633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
89733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bluetooth_a2dp_hw_params failed err: %d", err);
89833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
89933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
90033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
90133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_CONFIGURED);
90233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
90333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
90433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
90533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_CONFIGURING)
90633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_INITIALIZED);
90733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
90833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
90933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
91033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state)
91133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
91233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = state;
91333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->client_wait);
91433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
91533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
91671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kentstatic void __set_command(struct bluetooth_data *data, a2dp_command_t command)
91733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
91833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	VDBG("set_command %d\n", command);
91933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->command = command;
92033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->thread_wait);
92171d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	return;
92271d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent}
92371d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent
92471d71d08545fdc8f923119dea69f4c274ca60b71Ian Kentstatic void set_command(struct bluetooth_data *data, a2dp_command_t command)
92571d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent{
92671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_lock(&data->mutex);
92771d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	__set_command(data, command);
92833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_unlock(&data->mutex);
92933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
93033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9319ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood/* timeout is in milliseconds */
93233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int wait_for_start(struct bluetooth_data *data, int timeout)
93333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
93433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state = data->state;
9359ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	struct timeval tv;
93633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct timespec ts;
93733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err = 0;
93833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9399ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#ifdef ENABLE_TIMING
9409ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	uint64_t begin, end;
94133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
9429ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#endif
9439ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood
9449ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	gettimeofday(&tv, (struct timezone *) NULL);
9459ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_sec = tv.tv_sec + (timeout / 1000);
9469ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000L ) * 1000L;
94733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
94871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_lock(&data->mutex);
949b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent	while (state != A2DP_STATE_STARTED) {
95033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (state == A2DP_STATE_NONE)
9515abd6d6344fa6d196ab172f724e4b7e1a755689eEric Laurent			__set_command(data, A2DP_CMD_INIT);
95233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (state == A2DP_STATE_INITIALIZED)
95371d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			__set_command(data, A2DP_CMD_CONFIGURE);
95471d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		else if (state == A2DP_STATE_CONFIGURED) {
95571d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			__set_command(data, A2DP_CMD_START);
95671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		}
957b259b11bf5ac5259069d1144cd049e213352ed74Ian Kentagain:
958b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts);
959b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		if (err) {
960b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			/* don't timeout if we're done */
961b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			if (data->state == A2DP_STATE_STARTED) {
962b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				err = 0;
963b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				break;
964b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			}
965b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			if (err == ETIMEDOUT)
966b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent				break;
967b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			goto again;
968b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		}
969b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent
970b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent		if (state == data->state)
971b259b11bf5ac5259069d1144cd049e213352ed74Ian Kent			goto again;
97233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
97333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		state = data->state;
97471d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent
97571d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		if (state == A2DP_STATE_NONE) {
97671d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			err = ENODEV;
97771d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent			break;
97871d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent		}
97933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
98071d71d08545fdc8f923119dea69f4c274ca60b71Ian Kent	pthread_mutex_unlock(&data->mutex);
98133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
98233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
98333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
98433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("wait_for_start", begin, end);
98533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
98633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
98733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* pthread_cond_timedwait returns positive errors */
98833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return -err;
98933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
99033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
991be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kentstatic void a2dp_free(struct bluetooth_data *data)
992be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent{
993be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->client_wait);
994be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->thread_wait);
995be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_cond_destroy(&data->thread_start);
996be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	pthread_mutex_destroy(&data->mutex);
997be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	free(data);
998be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	return;
999be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent}
1000be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent
100133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void* a2dp_thread(void *d)
100233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
100333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
10046782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	a2dp_command_t command = A2DP_CMD_NONE;
100533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
100633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread started");
1007c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	prctl(PR_SET_NAME, (int)"a2dp_thread", 0, 0, 0);
100833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
1009281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_lock(&data->mutex);
1010281c324f0ba38b0720884b53d465b1420fac616aIan Kent
1011281c324f0ba38b0720884b53d465b1420fac616aIan Kent	data->started = 1;
1012281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_start);
1013281c324f0ba38b0720884b53d465b1420fac616aIan Kent
101433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (1)
101533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	{
10166782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		while (1) {
10176782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			pthread_cond_wait(&data->thread_wait, &data->mutex);
101833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10196782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* Initialization needed */
10206782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (data->state == A2DP_STATE_NONE &&
10216782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			    data->command != A2DP_CMD_QUIT) {
10226782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				bluetooth_init(data);
10236782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
10246782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent
10256782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* New state command signaled */
10266782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (command != data->command) {
10276782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				command = data->command;
10286782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				break;
10296782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
10306782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		}
103133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
103233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (command) {
103333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_CONFIGURE:
103433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_INITIALIZED)
103533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
103633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_configure(data);
103733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
103833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
103933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_START:
104033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_CONFIGURED)
104133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
104233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_start(data);
104333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
104433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
104533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_STOP:
104633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_STARTED)
104733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
104833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_stop(data);
104933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
105033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
105133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_QUIT:
105233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_close(data);
105333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				sbc_finish(&data->sbc);
1054be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent				a2dp_free(data);
105533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				goto done;
105633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
1057533b9f6e793e4c7aa09e7127077d8e9a2d388504Nick Pelly			case A2DP_CMD_INIT:
1058533b9f6e793e4c7aa09e7127077d8e9a2d388504Nick Pelly				/* already called bluetooth_init() */
105933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			default:
106033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
106133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
106233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
106333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
106433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
1065281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_unlock(&data->mutex);
106633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread finished");
106733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return NULL;
106833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
106933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
107033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_init(int rate, int channels, a2dpData* dataPtr)
107133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
107233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data;
107333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_t attr;
107433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
107533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
107633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_init rate: %d channels: %d", rate, channels);
107733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = NULL;
107833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data = malloc(sizeof(struct bluetooth_data));
107933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
108033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
108133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
108233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data, 0, sizeof(struct bluetooth_data));
108333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = -1;
108433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = -1;
108533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
10866782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	data->command = A2DP_CMD_NONE;
108733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
108833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(data->address, "00:00:00:00:00:00", 18);
108933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->rate = rate;
109033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->channels = channels;
109133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
109233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_init(&data->sbc, 0);
109333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
109433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_init(&data->mutex, NULL);
10955bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_init(&data->thread_start, NULL);
109633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->thread_wait, NULL);
109733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->client_wait, NULL);
109833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10995bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_lock(&data->mutex);
11005bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	data->started = 0;
11015bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
110233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_init(&attr);
110333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11045bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
11055bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	err = pthread_create(&data->thread, &attr, a2dp_thread, data);
11065bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	if (err) {
11075bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		/* If the thread create fails we must not wait */
11085bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_mutex_unlock(&data->mutex);
11095bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		err = -err;
11105bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		goto error;
11115bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
11125bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1113281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Make sure the state machine is ready and waiting */
11145bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	while (!data->started) {
11155bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_cond_wait(&data->thread_start, &data->mutex);
11165bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
11175bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1118281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Poke the state machine to get it going */
1119281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_wait);
1120281c324f0ba38b0720884b53d465b1420fac616aIan Kent
11215bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_unlock(&data->mutex);
11223da4d6ad9402b574ee4dc7923f1d27b1fa2302a0Ian Kent	pthread_attr_destroy(&attr);
112333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
112433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = data;
112533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
112633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
112733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_close(data);
11285bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	sbc_finish(&data->sbc);
11293da4d6ad9402b574ee4dc7923f1d27b1fa2302a0Ian Kent	pthread_attr_destroy(&attr);
1130be89a6e822dcb07e368a10fce392f2d19cc55d68Ian Kent	a2dp_free(data);
113133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
113333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
113433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_set_sink(a2dpData d, const char* address)
113633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
113733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
113833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (strncmp(data->address, address, 18)) {
113933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		strncpy(data->address, address, 18);
114067bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh		set_command(data, A2DP_CMD_INIT);
114133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
114233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
114333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
114433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_write(a2dpData d, const void* buffer, int count)
114533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
114633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
114733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t* src = (uint8_t *)buffer;
114833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;
114933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret = 0;
115033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long frames_left = count;
1151c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	int encoded;
1152c4e47c15ae8fe36673e7cdd7ee3caaffddb5071eNick Pelly	unsigned int written;
115333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *buff;
115433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int did_configure = 0;
115533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
115633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end;
115733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("********** a2dp_write **********");
115833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
115933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
116033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
116133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = wait_for_start(data, WRITE_TIMEOUT);
116233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
116333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
116433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
116533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	codesize = data->codesize;
116633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
116733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (frames_left >= codesize) {
116833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* Enough data to encode (sbc wants 512 byte blocks) */
116933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		encoded = sbc_encode(&(data->sbc), src, codesize,
117033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->buffer + data->count,
117133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					sizeof(data->buffer) - data->count,
117233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					&written);
117333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (encoded <= 0) {
117433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Encoding error %d", encoded);
117533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			goto done;
117633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
117733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("sbc_encode returned %d, codesize: %d, written: %d\n",
117833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			encoded, codesize, written);
117933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
118033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		src += encoded;
118133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->count += written;
118233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->frame_count++;
118333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->samples += encoded;
118433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->nsamples += encoded;
118533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
118633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* No space left for another frame then send */
11879d60b87413f23ef48d3cb24bb44f51745c02a332Yu Kang Ku		if ((data->count + written >= data->link_mtu) ||
11889d60b87413f23ef48d3cb24bb44f51745c02a332Yu Kang Ku				(data->count + written >= BUFFER_SIZE)) {
118933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("sending packet %d, count %d, link_mtu %u",
119033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->seq_num, data->count,
119133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->link_mtu);
119233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			err = avdtp_write(data);
119333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (err < 0)
119433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				return err;
119533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
119633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
119733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret += encoded;
119833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		frames_left -= encoded;
119933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
120033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
120133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (frames_left > 0)
120233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("%ld bytes left at end of a2dp_write\n", frames_left);
120333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
120433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
120533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
120633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
120733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("a2dp_write total", begin, end);
120833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
120933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return ret;
121033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
121133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
121233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_stop(a2dpData d)
121333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
121433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
121533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_stop\n");
121633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
121733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 0;
121833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
121933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_STOP);
122033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
122133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
122233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
122333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_cleanup(a2dpData d)
122433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
122533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
122633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_cleanup\n");
122733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_QUIT);
122833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
1229