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