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