liba2dp.c revision 6782d7bd225048e49ff485d06d8da5be8472fcf3
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
4233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "ipc.h"
4333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "sbc.h"
4433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "rtp.h"
4533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include "liba2dp.h"
4633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
4733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define LOG_NDEBUG 0
4833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define LOG_TAG "A2DP"
4933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#include <utils/Log.h>
5033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define ENABLE_DEBUG
5233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* #define ENABLE_VERBOSE */
5333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* #define ENABLE_TIMING */
5433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define BUFFER_SIZE 2048
5633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
5733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_DEBUG
5833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define DBG LOGD
5933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#else
6033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define DBG(fmt, arg...)
6133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
6233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
6333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_VERBOSE
6433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define VDBG LOGV
6533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#else
6633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define VDBG(fmt, arg...)
6733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
6833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
6933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifndef MIN
7033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh# define MIN(x, y) ((x) < (y) ? (x) : (y))
7133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
7233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
7333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifndef MAX
7433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh# define MAX(x, y) ((x) > (y) ? (x) : (y))
7533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
7633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
7733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define MAX_BITPOOL 64
7833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define MIN_BITPOOL 2
7933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define ERR LOGE
8133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* Number of packets to buffer in the stream socket */
8333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define PACKET_BUFFER_COUNT		10
8433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* timeout in milliseconds to prevent poll() from hanging indefinitely */
8633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#define POLL_TIMEOUT			1000
8733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh/* timeout in milliseconds for a2dp_write */
899ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#define WRITE_TIMEOUT			500
9033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
9333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_NONE = 0,
9433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_INITIALIZED,
9533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURING,
9633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_CONFIGURED,
9733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTING,
9833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STARTED,
9933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_STATE_STOPPING,
10033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_state_t;
10133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshtypedef enum {
10333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_NONE = 0,
10467bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh	A2DP_CMD_INIT,
10533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_CONFIGURE,
10633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_START,
10733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_STOP,
10833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	A2DP_CMD_QUIT,
10933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh} a2dp_command_t;
11033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
11133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstruct bluetooth_data {
11233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int link_mtu;					/* MTU for transport channel */
11333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd stream;			/* Audio stream filedescriptor */
11433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct pollfd server;			/* Audio daemon filedescriptor */
11533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state;				/* Current A2DP state */
11633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_command_t command;			/* Current command for a2dp_thread */
11733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_t thread;
11833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_t mutex;
1195bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	int started;
1205bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_t thread_start;
12133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t thread_wait;
12233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_t client_wait;
12333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
12433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t sbc_capabilities;
12533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_t sbc;				/* Codec data */
12633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	frame_duration;			/* length of an SBC frame in microseconds */
12733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;				/* SBC codesize */
12833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int samples;				/* Number of encoded samples */
12933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t buffer[BUFFER_SIZE];		/* Codec transfer buffer */
13033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int count;				/* Codec transfer buffer counter */
13133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
13233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int nsamples;				/* Cumulative number of codec samples */
13333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t seq_num;			/* Cumulative packet sequence */
13433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int frame_count;			/* Current frames in buffer*/
13533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
13633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char	address[20];
13733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	rate;
13833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int	channels;
13933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* used for pacing our writes to the output socket */
14133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t	next_write;
14233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh};
14333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
14433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint64_t get_microseconds()
14533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
14633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct timeval now;
14733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	gettimeofday(&now, NULL);
14833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return (now.tv_sec * 1000000UL + now.tv_usec);
14933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
15033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
15233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void print_time(const char* message, uint64_t then, uint64_t now)
15333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
15433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("%s: %lld us", message, now - then);
15533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
15633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
15733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
15833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data, const bt_audio_msg_header_t *msg);
15933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data, bt_audio_msg_header_t *outmsg,
16033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				int expected_type);
16133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data);
16233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state);
16333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
16433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
16533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_close(struct bluetooth_data *data)
16633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
16733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_close");
16833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->server.fd >= 0) {
16933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_service_close(data->server.fd);
17033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->server.fd = -1;
17133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
17233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
17433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
17533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
17633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
17733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
17833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
17933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
18033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
18133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_start(struct bluetooth_data *data)
18233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
18333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char c = 'w';
18433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
18533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_req *start_req = (void*) buf;
18633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_start_stream_rsp *start_rsp = (void*) buf;
18733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_new_stream_ind *streamfd_ind = (void*) buf;
18833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int opt_name, err, bytes;
18933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
19033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_start");
19133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STARTING;
19233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send start */
19333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(start_req, 0, BT_SUGGESTED_BUFFER_SIZE);
19474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.type = BT_REQUEST;
19574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.name = BT_START_STREAM;
19674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	start_req->h.length = sizeof(*start_req);
19733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
19833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
19933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &start_req->h);
20033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
20133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
20233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
20333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	start_rsp->h.length = sizeof(*start_rsp);
20433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &start_rsp->h, BT_START_STREAM);
20533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
20633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
20733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
20874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	streamfd_ind->h.length = sizeof(*streamfd_ind);
20933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &streamfd_ind->h, BT_NEW_STREAM);
21033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
21133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
21233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
21333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
21433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd < 0) {
21533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_get_data_fd failed, errno: %d", errno);
21633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
21733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
21833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
21933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.events = POLLOUT;
22033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
22133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* set our socket buffer to the size of PACKET_BUFFER_COUNT packets */
22233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bytes = data->link_mtu * PACKET_BUFFER_COUNT;
22333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setsockopt(data->stream.fd, SOL_SOCKET, SO_SNDBUF, &bytes,
22433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			sizeof(bytes));
22533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
22633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
22733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
22833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
22933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->nsamples = 0;
23033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num = 0;
23133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
23233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->next_write = 0;
23333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_STARTED);
23533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
23633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
23733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
23833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* set state to A2DP_STATE_INITIALIZED to force reconfiguration */
23933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_STARTING)
24033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_INITIALIZED);
24133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
24233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
24333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
24433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_stop(struct bluetooth_data *data)
24533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
24633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
24733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_req *stop_req = (void*) buf;
24833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_stop_stream_rsp *stop_rsp = (void*) buf;
24933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
25033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_stop");
25233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_STOPPING;
25433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->stream.fd >= 0) {
25533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		close(data->stream.fd);
25633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->stream.fd = -1;
25733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
25833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
25933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* send stop request */
26033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(stop_req, 0, BT_SUGGESTED_BUFFER_SIZE);
26174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.type = BT_REQUEST;
26274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.name = BT_STOP_STREAM;
26374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	stop_req->h.length = sizeof(*stop_req);
26433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
26533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &stop_req->h);
26633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
26733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
26833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
26933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	stop_rsp->h.length = sizeof(*stop_rsp);
27033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &stop_rsp->h, BT_STOP_STREAM);
27133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
27233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
27333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
27433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
27533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_STOPPING)
27633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_CONFIGURED);
27733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
27833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
27933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
28033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode)
28133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
28233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (freq) {
28333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_16000:
28433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_32000:
28533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
28633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_44100:
28733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
28833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
28933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
29033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 31;
29133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
29233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
29333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
29433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
29533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
29633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 53;
29733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
29833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_SBC_SAMPLING_FREQ_48000:
29933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (mode) {
30033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
30133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
30233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 29;
30333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
30433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
30533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
30633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
30733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Invalid channel mode %u", mode);
30833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			return 51;
30933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
31033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
31133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Invalid sampling freq %u", freq);
31233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 53;
31333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
31433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
31533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
31633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_init(struct bluetooth_data *data)
31733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
31833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t *cap = &data->sbc_capabilities;
31933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	unsigned int max_bitpool, min_bitpool;
32033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int dir;
32133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
32233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->rate) {
32333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 48000:
32433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
32533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
32633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 44100:
32733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
32833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
32933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 32000:
33033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
33133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
33233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case 16000:
33333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
33433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
33533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	default:
33633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Rate %d not supported", data->rate);
33733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
33833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
33933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
34033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->channels == 2) {
34133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
34233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
34333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
34433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
34533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
34633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
34733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
34833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
34933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
35033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
35133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
35233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!cap->channel_mode) {
35333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported channel modes");
35433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
35533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
35633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
35733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
35833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
35933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
36033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
36133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
36233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
36333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
36433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
36533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
36633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported block lengths");
36733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
36833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
36933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
37033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->subbands & BT_A2DP_SUBBANDS_8)
37133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_8;
37233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->subbands & BT_A2DP_SUBBANDS_4)
37333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->subbands = BT_A2DP_SUBBANDS_4;
37433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
37533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("No supported subbands");
37633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
37733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
37833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
37933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
38033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
38133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
38233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
38333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
38433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
38533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		max_bitpool = MIN(default_bitpool(cap->frequency,
38633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->channel_mode),
38733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					cap->max_bitpool);
38833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
38933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->min_bitpool = min_bitpool;
39033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	cap->max_bitpool = max_bitpool;
39133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
39333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
39433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void bluetooth_a2dp_setup(struct bluetooth_data *data)
39633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
39733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_capabilities_t active_capabilities = data->sbc_capabilities;
39833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
39933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_reinit(&data->sbc, 0);
40033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
40133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
40233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_16000;
40333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
40433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
40533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_32000;
40633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
40733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
40833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_44100;
40933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
41133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.frequency = SBC_FREQ_48000;
41233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
41433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_MONO;
41533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
41733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_DUAL_CHANNEL;
41833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
41933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
42033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_STEREO;
42133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
42333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.mode = SBC_MODE_JOINT_STEREO;
42433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.allocation = active_capabilities.allocation_method
42633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				== BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR
42733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				: SBC_AM_LOUDNESS;
42833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
42933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.subbands) {
43033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_4:
43133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_4;
43233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
43333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_SUBBANDS_8:
43433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.subbands = SBC_SB_8;
43533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
43633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
43733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
43833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (active_capabilities.block_length) {
43933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_4:
44033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_4;
44133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
44233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_8:
44333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_8;
44433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
44533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_12:
44633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_12;
44733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
44833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	case BT_A2DP_BLOCK_LENGTH_16:
44933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.blocks = SBC_BLK_16;
45033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		break;
45133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
45233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->sbc.bitpool = active_capabilities.max_bitpool;
45433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->codesize = sbc_get_codesize(&data->sbc);
45533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_duration = sbc_get_frame_duration(&data->sbc);
45633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("frame_duration: %d us", data->frame_duration);
45733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
45833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
45933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_a2dp_hw_params(struct bluetooth_data *data)
46033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
46133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
46233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_req *open_req = (void *) buf;
46333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_open_rsp *open_rsp = (void *) buf;
46433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_req *setconf_req = (void*) buf;
46533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_set_configuration_rsp *setconf_rsp = (void*) buf;
46633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
46733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
46874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memset(open_req, 0, BT_SUGGESTED_BUFFER_SIZE);
46933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.type = BT_REQUEST;
47033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.name = BT_OPEN;
47133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->h.length = sizeof(*open_req);
47233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(open_req->destination, data->address, 18);
47374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_req->seid = data->sbc_capabilities.capability.seid;
47433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	open_req->lock = BT_WRITE_LOCK;
47533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
47674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_send(data, &open_req->h);
47774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
47874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
47933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
48074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	open_rsp->h.length = sizeof(*open_rsp);
48174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = audioservice_expect(data, &open_rsp->h, BT_OPEN);
48274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
48374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
48433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
48574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	err = bluetooth_a2dp_init(data);
48674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err < 0)
48774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
48833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
48933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
49033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(setconf_req, 0, BT_SUGGESTED_BUFFER_SIZE);
49133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.type = BT_REQUEST;
49233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.name = BT_SET_CONFIGURATION;
49374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	setconf_req->h.length = sizeof(*setconf_req);
49474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&setconf_req->codec, &data->sbc_capabilities,
49574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						sizeof(data->sbc_capabilities));
49633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
49733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
49833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->codec.length = sizeof(data->sbc_capabilities);
49933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	setconf_req->h.length += setconf_req->codec.length - sizeof(setconf_req->codec);
50033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
50133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_a2dp_hw_params sending configuration:\n");
50233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.channel_mode) {
50333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_MONO:
50433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: MONO\n");
50533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
50633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
50733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: DUAL CHANNEL\n");
50833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
50933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_STEREO:
51033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: STEREO\n");
51133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
51233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
51333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: JOINT STEREO\n");
51433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
51533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
51633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tchannel_mode: UNKNOWN (%d)\n",
51733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.channel_mode);
51833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
51933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.frequency) {
52033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_16000:
52133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 16000\n");
52233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
52333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_32000:
52433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 32000\n");
52533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
52633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_44100:
52733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 44100\n");
52833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
52933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_SBC_SAMPLING_FREQ_48000:
53033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: 48000\n");
53133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
53233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
53333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tfrequency: UNKNOWN (%d)\n",
53433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.frequency);
53533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
53633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.allocation_method) {
53733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_SNR:
53833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: SNR\n");
53933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_ALLOCATION_LOUDNESS:
54133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: LOUDNESS\n");
54233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
54333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
54433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tallocation_method: UNKNOWN (%d)\n",
54533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.allocation_method);
54633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
54733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.subbands) {
54833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_4:
54933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 4\n");
55033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_SUBBANDS_8:
55233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: 8\n");
55333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
55433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
55533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tsubbands: UNKNOWN (%d)\n",
55633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.subbands);
55733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
55833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	switch (data->sbc_capabilities.block_length) {
55933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_4:
56033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 4\n");
56133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_8:
56333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 8\n");
56433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_12:
56633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 12\n");
56733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
56833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		case BT_A2DP_BLOCK_LENGTH_16:
56933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: 16\n");
57033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			break;
57133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		default:
57233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("\tblock_length: UNKNOWN (%d)\n",
57333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				data->sbc_capabilities.block_length);
57433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
57533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmin_bitpool: %d\n", data->sbc_capabilities.min_bitpool);
57633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tmax_bitpool: %d\n", data->sbc_capabilities.max_bitpool);
57733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
57833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &setconf_req->h);
57933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
58033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
58133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
58233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &setconf_rsp->h, BT_SET_CONFIGURATION);
58333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
58433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
58533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
58633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->link_mtu = setconf_rsp->link_mtu;
58733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("MTU: %d", data->link_mtu);
58833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
58933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Setup SBC encoder now we agree on parameters */
59033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_a2dp_setup(data);
59133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
59233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
59333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.allocation, data->sbc.subbands, data->sbc.blocks,
59433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->sbc.bitpool);
59533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
59633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
59733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
59833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
59933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int avdtp_write(struct bluetooth_data *data)
60033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
60133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int ret = 0;
60233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_header *header;
60333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct rtp_payload *payload;
60433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
60533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t now;
60633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long duration = data->frame_duration * data->frame_count;
60733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
60833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end, begin2, end2;
60933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
61033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
61133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header = (struct rtp_header *)data->buffer;
61333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload = (struct rtp_payload *)(data->buffer + sizeof(*header));
61433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data->buffer, 0, sizeof(*header) + sizeof(*payload));
61633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
61733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	payload->frame_count = data->frame_count;
61833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->v = 2;
61933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->pt = 1;
62033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->sequence_number = htons(data->seq_num);
62133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->timestamp = htonl(data->nsamples);
62233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	header->ssrc = htonl(1);
62333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
62433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.revents = 0;
62533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
62633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin2 = get_microseconds();
62733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
62833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = poll(&data->stream, 1, POLL_TIMEOUT);
62933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
63033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end2 = get_microseconds();
63133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("poll", begin2, end2);
63233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
63333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (ret == 1 && data->stream.revents == POLLOUT) {
63433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		long ahead = 0;
63533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		now = get_microseconds();
63633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
63733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (data->next_write) {
63833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ahead = data->next_write - now;
63933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
64033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			DBG("duration: %ld, ahead: %ld", duration, ahead);
64133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
64233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (ahead > 0) {
64333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				/* too fast, need to throttle */
64433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				usleep(ahead);
64533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			}
64633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		} else {
64733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			data->next_write = now;
64833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
64933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ahead < 0) {
65033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			/* fallen too far behind, don't try to catch up */
65133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("ahead < 0, resetting next_write");
65233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			data->next_write = 0;
65333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		} else {
65433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			/* advance next_write by duration */
65533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			data->next_write += duration;
65633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
65733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
65833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
65933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		begin2 = get_microseconds();
66033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
66133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret = send(data->stream.fd, data->buffer, data->count, MSG_NOSIGNAL);
66233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
66333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		end2 = get_microseconds();
66433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		print_time("send", begin2, end2);
66533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
66633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret < 0) {
66733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			/* can happen during normal remote disconnect */
66833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("send() failed: %d (errno %s)", ret, strerror(errno));
66933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
67033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (ret == -EPIPE) {
67133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
67233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
67333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	} else {
67433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* can happen during normal remote disconnect */
67533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("poll() failed: %d (revents = %d, errno %s)",
67633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				ret, data->stream.revents, strerror(errno));
67733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
67833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
67933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* Reset buffer of data to send */
68033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
68133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->frame_count = 0;
68233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->samples = 0;
68333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->seq_num++;
68433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
68533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
68633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
68733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("avdtp_write", begin, end);
68833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
68933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0; /* always return success */
69033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
69133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
69233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_send(struct bluetooth_data *data,
69333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		const bt_audio_msg_header_t *msg)
69433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
69533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
69633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint16_t length;
69733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
69874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE;
69933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
70033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	VDBG("sending %s", bt_audio_strmsg(msg->msg_type));
70133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (send(data->server.fd, msg, length,
70233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			MSG_NOSIGNAL) > 0)
70333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = 0;
70433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	else {
70533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		err = -errno;
70633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("Error sending data to audio service: %s(%d)",
70733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			strerror(errno), errno);
70833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
70933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
71033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
71133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
71233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
71333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
71433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
71533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_recv(struct bluetooth_data *data,
71633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *inmsg)
71733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
71833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret;
71933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *type, *name;
72074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	uint16_t length;
72133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
722104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE;
72333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
72433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	ret = recv(data->server.fd, inmsg, length, 0);
72574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (ret < 0) {
72674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -errno;
72774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Error receiving IPC data from bluetoothd: %s (%d)",
72874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh						strerror(errno), errno);
72933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (err == -EPIPE)
73033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			bluetooth_close(data);
73174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) {
73274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Too short (%d bytes) IPC packet from bluetoothd", ret);
73374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
734104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh	} else if (inmsg->type == BT_ERROR) {
735104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		bt_audio_error_t *error = (bt_audio_error_t *)inmsg;
736104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		ret = recv(data->server.fd, &error->posix_errno,
737104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				sizeof(error->posix_errno), 0);
738104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		if (ret < 0) {
739104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -errno;
740104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("Error receiving error code for BT_ERROR: %s (%d)",
741104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh						strerror(errno), errno);
742104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			if (err == -EPIPE)
743104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh				bluetooth_close(data);
744104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		} else {
745104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			ERR("%s failed : %s(%d)",
746104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					bt_audio_strname(error->h.name),
747104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					strerror(error->posix_errno),
748104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh					error->posix_errno);
749104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh			err = -error->posix_errno;
750104ccdd9639814000c5a817b3e22bee4a1c89598Jaikumar Ganesh		}
75174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	} else {
75274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		type = bt_audio_strtype(inmsg->type);
75374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		name = bt_audio_strname(inmsg->name);
75474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if (type && name) {
75574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			DBG("Received %s - %s", type, name);
75674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = 0;
75774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		} else {
75874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			err = -EINVAL;
75974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			ERR("Bogus message type %d - name %d"
76074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					" received from audio service",
76174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					inmsg->type, inmsg->name);
76274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		}
76374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
76474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
76533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
76633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
76733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
76833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int audioservice_expect(struct bluetooth_data *data,
76933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		bt_audio_msg_header_t *rsp_hdr, int expected_name)
77033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
77174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int err = audioservice_recv(data, rsp_hdr);
77274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
77374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (err != 0)
77474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return err;
77574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh
77674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (rsp_hdr->name != expected_name) {
77774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		err = -EINVAL;
77874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		ERR("Bogus message %s received while %s was expected",
77974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(rsp_hdr->name),
78074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				bt_audio_strname(expected_name));
78174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
78274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return err;
78333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
78433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
78533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
78633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_init(struct bluetooth_data *data)
78733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
78833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int sk, err;
78933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
79033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_init");
79133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
79233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sk = bt_audio_service_open();
79333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (sk <= 0) {
79433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bt_audio_service_open failed\n");
79533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -errno;
79633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
79733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
79833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = sk;
79933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.events = POLLIN;
80033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_INITIALIZED;
80133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
80233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
80333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
80433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
80533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_parse_capabilities(struct bluetooth_data *data,
80674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh					struct bt_get_capabilities_rsp *rsp)
80733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
80874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	int bytes_left = rsp->h.length - sizeof(*rsp);
80974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	codec_capabilities_t *codec = (void *) rsp->data;
81033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP)
81274c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return 0;
81333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	while (bytes_left > 0) {
81574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		if ((codec->type == BT_A2DP_SBC_SINK) &&
81674c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh				!(codec->lock & BT_WRITE_LOCK))
81774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			break;
81833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
81974c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		bytes_left -= codec->length;
82074c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		codec = (void *) codec + codec->length;
82174c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	}
82233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
82374c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	if (bytes_left <= 0 ||
82474c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh			codec->length != sizeof(data->sbc_capabilities))
82574c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh		return -EINVAL;
82633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
82774c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	memcpy(&data->sbc_capabilities, codec, codec->length);
82874c3402b5b785402f2632398bca971719f5aa1a5Jaikumar Ganesh	return 0;
82933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
83033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int bluetooth_configure(struct bluetooth_data *data)
83333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
83433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	char buf[BT_SUGGESTED_BUFFER_SIZE];
83533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_req *getcaps_req = (void*) buf;
83633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bt_get_capabilities_rsp *getcaps_rsp = (void*) buf;
83733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
83833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
83933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("bluetooth_configure");
84033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_CONFIGURING;
84233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(getcaps_req, 0, BT_SUGGESTED_BUFFER_SIZE);
84333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.type = BT_REQUEST;
84433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.name = BT_GET_CAPABILITIES;
84533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
84633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags = 0;
84733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
84833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(getcaps_req->destination, data->address, 18);
84933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
85033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_req->h.length = sizeof(*getcaps_req);
85133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_send(data, &getcaps_req->h);
85333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
85433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_send failed for BT_GETCAPABILITIES_REQ\n");
85533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
85633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
85733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
85833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	getcaps_rsp->h.length = 0;
85933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = audioservice_expect(data, &getcaps_rsp->h, BT_GET_CAPABILITIES);
86033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
86133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("audioservice_expect failed for BT_GETCAPABILITIES_RSP\n");
86233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
86333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
86433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
86533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_parse_capabilities(data, getcaps_rsp);
86633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = bluetooth_a2dp_hw_params(data);
86733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0) {
86833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("bluetooth_a2dp_hw_params failed err: %d", err);
86933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		goto error;
87033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
87133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_state(data, A2DP_STATE_CONFIGURED);
87333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
87433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
87533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
87633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (data->state == A2DP_STATE_CONFIGURING)
87733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		set_state(data, A2DP_STATE_INITIALIZED);
87833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
87933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
88033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_state(struct bluetooth_data *data, a2dp_state_t state)
88233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
88333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = state;
88433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->client_wait);
88533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
88633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
88733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void set_command(struct bluetooth_data *data, a2dp_command_t command)
88833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
88933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	VDBG("set_command %d\n", command);
89033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_lock(&data->mutex);
89133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->command = command;
89233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_signal(&data->thread_wait);
89333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_unlock(&data->mutex);
89433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
89533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
8969ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood/* timeout is in milliseconds */
89733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic int wait_for_start(struct bluetooth_data *data, int timeout)
89833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
89933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	a2dp_state_t state = data->state;
9009ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	struct timeval tv;
90133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct timespec ts;
90233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err = 0;
90333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9049ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#ifdef ENABLE_TIMING
9059ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	uint64_t begin, end;
90633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
9079ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood#endif
9089ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood
9099ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	gettimeofday(&tv, (struct timezone *) NULL);
9109ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_sec = tv.tv_sec + (timeout / 1000);
9119ad46087066dbeda8def8ba0fbda32b4ea7074baMike Lockwood	ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000L ) * 1000L;
91233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
91333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (state != A2DP_STATE_STARTED && !err) {
91433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (state == A2DP_STATE_NONE)
91567bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh			set_command(data, A2DP_CMD_INIT);
91633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (state == A2DP_STATE_INITIALIZED)
91733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			set_command(data, A2DP_CMD_CONFIGURE);
91833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		else if (state == A2DP_STATE_CONFIGURED)
91933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			set_command(data, A2DP_CMD_START);
92033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
92133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		pthread_mutex_lock(&data->mutex);
92233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		while ((err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts))
92333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				== EINTR) ;
92433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		state = data->state;
92533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		pthread_mutex_unlock(&data->mutex);
92633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
92733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
92833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
92933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
93033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("wait_for_start", begin, end);
93133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
93233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
93333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	/* pthread_cond_timedwait returns positive errors */
93433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return -err;
93533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
93633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
93733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshstatic void* a2dp_thread(void *d)
93833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
93933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
9406782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	a2dp_command_t command = A2DP_CMD_NONE;
94133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
94233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread started");
94333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	prctl(PR_SET_NAME, "a2dp_thread", 0, 0, 0);
94433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
945281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_lock(&data->mutex);
946281c324f0ba38b0720884b53d465b1420fac616aIan Kent
947281c324f0ba38b0720884b53d465b1420fac616aIan Kent	data->started = 1;
948281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_start);
949281c324f0ba38b0720884b53d465b1420fac616aIan Kent
95033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (1)
95133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	{
9526782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		while (1) {
9536782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			pthread_cond_wait(&data->thread_wait, &data->mutex);
95433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
9556782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* Initialization needed */
9566782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (data->state == A2DP_STATE_NONE &&
9576782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			    data->command != A2DP_CMD_QUIT) {
9586782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				bluetooth_init(data);
9596782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
9606782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent
9616782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			/* New state command signaled */
9626782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			if (command != data->command) {
9636782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				command = data->command;
9646782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent				break;
9656782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent			}
9666782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent		}
96733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
96833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		switch (command) {
96967bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh			case A2DP_CMD_INIT:
97067bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh				if (data->state != A2DP_STATE_NONE)
97167bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh					break;
97267bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh				bluetooth_init(data);
97367bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh				break;
97433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_CONFIGURE:
97533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_INITIALIZED)
97633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
97733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_configure(data);
97833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
97933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
98033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_START:
98133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_CONFIGURED)
98233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
98333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_start(data);
98433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
98533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
98633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_STOP:
98733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				if (data->state != A2DP_STATE_STARTED)
98833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					break;
98933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_stop(data);
99033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
99133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
99233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			case A2DP_CMD_QUIT:
99333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				bluetooth_close(data);
99433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				sbc_finish(&data->sbc);
99533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				free(data);
99633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				goto done;
99733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
99833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			default:
99933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				break;
100033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
100133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
100233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
100333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
1004281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_mutex_unlock(&data->mutex);
100533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_thread finished");
100633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return NULL;
100733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
100833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
100933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_init(int rate, int channels, a2dpData* dataPtr)
101033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
101133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data;
101233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_t attr;
101333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err;
101433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
101533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_init rate: %d channels: %d", rate, channels);
101633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = NULL;
101733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data = malloc(sizeof(struct bluetooth_data));
101833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
101933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return -1;
102033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
102133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	memset(data, 0, sizeof(struct bluetooth_data));
102233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->server.fd = -1;
102333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->stream.fd = -1;
102433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->state = A2DP_STATE_NONE;
10256782d7bd225048e49ff485d06d8da5be8472fcf3Ian Kent	data->command = A2DP_CMD_NONE;
102633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
102733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	strncpy(data->address, "00:00:00:00:00:00", 18);
102833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->rate = rate;
102933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	data->channels = channels;
103033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
103133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	sbc_init(&data->sbc, 0);
103233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
103333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_mutex_init(&data->mutex, NULL);
10345bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_cond_init(&data->thread_start, NULL);
103533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->thread_wait, NULL);
103633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_cond_init(&data->client_wait, NULL);
103733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
10385bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_lock(&data->mutex);
10395bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	data->started = 0;
10405bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
104133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_init(&attr);
104233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10435bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
10445bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	err = pthread_create(&data->thread, &attr, a2dp_thread, data);
10455bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	if (err) {
10465bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		/* If the thread create fails we must not wait */
10475bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_mutex_unlock(&data->mutex);
10485bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		err = -err;
10495bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		goto error;
10505bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
10515bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1052281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Make sure the state machine is ready and waiting */
10535bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	while (!data->started) {
10545bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent		pthread_cond_wait(&data->thread_start, &data->mutex);
10555bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	}
10565bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent
1057281c324f0ba38b0720884b53d465b1420fac616aIan Kent	/* Poke the state machine to get it going */
1058281c324f0ba38b0720884b53d465b1420fac616aIan Kent	pthread_cond_signal(&data->thread_wait);
1059281c324f0ba38b0720884b53d465b1420fac616aIan Kent
10605bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	pthread_mutex_unlock(&data->mutex);
106133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
106233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	*dataPtr = data;
106333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
106433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesherror:
106533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	bluetooth_close(data);
10665bac662a139181195fae0a6292bdc6c12ba6f463Ian Kent	sbc_finish(&data->sbc);
106733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	free(data);
106833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
106933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return err;
107033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
107133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
107233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_set_sink(a2dpData d, const char* address)
107333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
107433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
107533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (strncmp(data->address, address, 18)) {
107633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		strncpy(data->address, address, 18);
107767bf8f93bc209d3d8873d41662796ecec0d6524cJaikumar Ganesh		set_command(data, A2DP_CMD_INIT);
107833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
107933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
108033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
108133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_write(a2dpData d, const void* buffer, int count)
108233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
108333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
108433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint8_t* src = (uint8_t *)buffer;
108533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int codesize;
108633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int err, ret = 0;
108733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	long frames_left = count;
108833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int encoded, written;
108933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	const char *buff;
109033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	int did_configure = 0;
109133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
109233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	uint64_t begin, end;
109333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("********** a2dp_write **********");
109433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	begin = get_microseconds();
109533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
109633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
109733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	err = wait_for_start(data, WRITE_TIMEOUT);
109833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (err < 0)
109933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return err;
110033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
110133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	codesize = data->codesize;
110233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
110333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	while (frames_left >= codesize) {
110433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* Enough data to encode (sbc wants 512 byte blocks) */
110533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		encoded = sbc_encode(&(data->sbc), src, codesize,
110633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->buffer + data->count,
110733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					sizeof(data->buffer) - data->count,
110833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					&written);
110933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (encoded <= 0) {
111033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			ERR("Encoding error %d", encoded);
111133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			goto done;
111233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
111333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		VDBG("sbc_encode returned %d, codesize: %d, written: %d\n",
111433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			encoded, codesize, written);
111533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
111633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		src += encoded;
111733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->count += written;
111833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->frame_count++;
111933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->samples += encoded;
112033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		data->nsamples += encoded;
112133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
112233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		/* No space left for another frame then send */
112333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		if (data->count + written >= data->link_mtu) {
112433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			VDBG("sending packet %d, count %d, link_mtu %u",
112533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->seq_num, data->count,
112633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh					data->link_mtu);
112733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			err = avdtp_write(data);
112833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh			if (err < 0)
112933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh				return err;
113033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		}
113133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ret += encoded;
113333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		frames_left -= encoded;
113433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	}
113533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (frames_left > 0)
113733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		ERR("%ld bytes left at end of a2dp_write\n", frames_left);
113833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
113933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshdone:
114033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#ifdef ENABLE_TIMING
114133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	end = get_microseconds();
114233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	print_time("a2dp_write total", begin, end);
114333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh#endif
114433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return ret;
114533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
114633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
114733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshint a2dp_stop(a2dpData d)
114833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
114933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
115033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_stop\n");
115133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	if (!data)
115233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh		return 0;
115333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
115433e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_STOP);
115533e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	return 0;
115633e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
115733e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh
115833e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganeshvoid a2dp_cleanup(a2dpData d)
115933e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh{
116033e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	struct bluetooth_data* data = (struct bluetooth_data*)d;
116133e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	DBG("a2dp_cleanup\n");
116233e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh	set_command(data, A2DP_CMD_QUIT);
116333e9fec43232e0341dba27786ec207c0d366b8b2Jaikumar Ganesh}
1164