1be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/* 2be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * Copyright (C) 2008-2011 The Android Open Source Project 3be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * 4be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * This library is free software; you can redistribute it and/or 5be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * modify it under the terms of the GNU Lesser General Public 6be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * License as published by the Free Software Foundation; either 7be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * version 2.1 of the License, or (at your option) any later version. 8be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * 9be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * This library is distributed in the hope that it will be useful, 10be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * but WITHOUT ANY WARRANTY; without even the implied warranty of 11be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * Lesser General Public License for more details. 13be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * 14be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * You should have received a copy of the GNU Lesser General Public 15be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * License along with this library; if not, write to the Free Software 16be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * 18be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin */ 19be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 20be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define LOG_TAG "a2dp_audio_hw" 21be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin//#define LOG_NDEBUG 0 22be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 23be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <errno.h> 24be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <pthread.h> 25be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <stdint.h> 26be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <sys/time.h> 27be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 28be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <cutils/log.h> 29be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <cutils/str_parms.h> 30be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 31be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <hardware/hardware.h> 325ca3dfce0e1c35f913f569049bd3f89204bddf92Dima Zavin#include <system/audio.h> 338126b3eb0ce7d77577aa364c1a0066c0d2334d19Dima Zavin#include <hardware/audio.h> 34be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 35be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <hardware_legacy/power.h> 36be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 37be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include "liba2dp.h" 38be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 39d6ae61e0932fb5c5a35914f35c9074c364f8e6e0Eric Laurent/* for backward compatibility with older audio framework */ 40d6ae61e0932fb5c5a35914f35c9074c364f8e6e0Eric Laurent#ifndef AUDIO_PARAMETER_A2DP_SINK_ADDRESS 41d6ae61e0932fb5c5a35914f35c9074c364f8e6e0Eric Laurent #define AUDIO_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address" 42d6ae61e0932fb5c5a35914f35c9074c364f8e6e0Eric Laurent#endif 43d6ae61e0932fb5c5a35914f35c9074c364f8e6e0Eric Laurent 44be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_WAKE_LOCK_NAME "A2dpOutputStream" 45be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define MAX_WRITE_RETRIES 5 46be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 47be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_SUSPENDED_PARM "A2dpSuspended" 48be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define BLUETOOOTH_ENABLED_PARM "bluetooth_enabled" 49be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 50be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 51355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* number of periods in pcm buffer (one period corresponds to buffer size reported to audio flinger 52355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * by out_get_buffer_size() */ 53355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_NUM_PERIODS 6 54355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_standby_stream_locked() for 2dp_write() to complete */ 55355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_WRITE_COMPLETION_TIMEOUT_MS 5000 56355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_write() for frames to be available in in write thread buffer */ 5705675015d13729f7da5bf32c88264c68e02d6028Eric Laurent#define BUF_WRITE_AVAILABILITY_TIMEOUT_MS 5000 58355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum number of attempts to wait for a write completion in out_standby_stream_locked() */ 59355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define MAX_WRITE_COMPLETION_ATTEMPTS 5 60355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 61355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* NOTE: there are 2 mutexes used by the a2dp output stream. 62355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * - lock: protects all calls to a2dp lib functions (a2dp_stop(), a2dp_cleanup()...). 63355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * One exception is a2dp_write() which is also protected by the flag write_busy. This is because 64355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * out_write() cannot block waiting for a2dp_write() to complete because this function 65355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * can sleep to throttle the A2DP bit rate. 66355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * This flag is always set/reset and tested with "lock" mutex held. 67355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * - buf_lock: protects access to pcm buffer read and write indexes. 68355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * 69355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * The locking order is always as follows: 70355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * buf_lock -> lock 71355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * 72355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * If you need to hold the adev_a2dp->lock AND the astream_out->lock or astream_out->buf_lock, 73355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * you MUST take adev_a2dp lock first!! 74be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin */ 75be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 76be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out; 77be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct adev_a2dp { 78be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_hw_device device; 79be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 80be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_mode_t mode; 81be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool bt_enabled; 82be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool suspended; 83be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 84be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_t lock; 85be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 86be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *output; 87be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 88be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 89be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out { 90be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out stream; 91be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 92be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t sample_rate; 93be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin size_t buffer_size; 94be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t channels; 9580e611bd026bf4134abd9e1908b677dc32b8bd91Glenn Kasten audio_format_t format; 96be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 97be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int fd; 98be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool standby; 99be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int start_count; 100be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int retry_count; 101be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin void* data; 102be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 103355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_t lock; /* see NOTE on mutex locking order above */ 104be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 105be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_devices_t device; 106be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint64_t last_write_time; 107be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t buffer_duration_us; 108be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 109be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool bt_enabled; 110be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool suspended; 111be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char a2dp_addr[20]; 112355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 113355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t *buf; /* pcm buffer between audioflinger thread and write thread*/ 114355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_size; /* size of pcm buffer in frames */ 115355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_rd_idx; /* read index in pcm buffer, in frames*/ 116355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_wr_idx; /* write index in pcm buffer, in frames */ 117355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_frames_ready; /* number of frames ready for writing to a2dp sink */ 118355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_t buf_lock; /* mutex protecting read and write indexes */ 119355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* see NOTE on mutex locking order above */ 120355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_t buf_cond; /* condition signaling data write/read to/from pcm buffer */ 121355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_t buf_thread; /* thread reading data from buffer and writing to a2dp sink*/ 122355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bool buf_thread_exit; /* flag requesting write thread exit */ 123355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bool write_busy; /* indicates that a write to a2dp sink is in progress and that 124355afe9a49d429650c955894220caebc1db3b1cfEric Laurent standby must wait for this flag to be cleared by write thread */ 125355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_t write_cond; /* condition associated with write_busy flag */ 126be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 127be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 128be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint64_t system_time(void) 129be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 130be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct timespec t; 131be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 132be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin t.tv_sec = t.tv_nsec = 0; 133be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin clock_gettime(CLOCK_MONOTONIC, &t); 134be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 135be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return t.tv_sec*1000000000LL + t.tv_nsec; 136be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 137be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 138be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/** audio_stream_out implementation **/ 139be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_sample_rate(const struct audio_stream *stream) 140be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 141be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 142be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->sample_rate; 143be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 144be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 145be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 146be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 147be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 148be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 1496934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 150be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 151be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 152be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 153be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t out_get_buffer_size(const struct audio_stream *stream) 154be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 155be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 156be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->buffer_size; 157be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 158be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 159be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_channels(const struct audio_stream *stream) 160be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 161be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 162be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->channels; 163be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 164be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 16580e611bd026bf4134abd9e1908b677dc32b8bd91Glenn Kastenstatic audio_format_t out_get_format(const struct audio_stream *stream) 166be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 167be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 168be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->format; 169be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 170be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 17180e611bd026bf4134abd9e1908b677dc32b8bd91Glenn Kastenstatic audio_format_t out_set_format(struct audio_stream *stream, audio_format_t format) 172be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 173be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 1746934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 175be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 176be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 177be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 178be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_dump(const struct audio_stream *stream, int fd) 179be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 180be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 181be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 182be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 183be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_latency(const struct audio_stream_out *stream) 184be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 185be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 186be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 18762215e25c389f985f713ffa31dd74b76d31a38c3Eric Laurent return ((out->buffer_duration_us * BUF_NUM_PERIODS) / 1000) + 200; 188be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 189be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 190be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_volume(struct audio_stream_out *stream, float left, 191be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin float right) 192be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 193be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 194be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 195be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 196be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_get_render_position(const struct audio_stream_out *stream, 197be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t *dsp_frames) 198be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 199be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 200be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 201be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 202be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_init_locked(struct astream_out *out, const char *addr) 203be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 204be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 205be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 206be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) 207be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 208be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 209be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: shouldn't this use the sample_rate/channel_count from 'out'? */ 210be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = a2dp_init(44100, 2, &out->data); 211be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret < 0) { 2126934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("a2dp_init failed err: %d\n", ret); 213be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->data = NULL; 214be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 215be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 216be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 217be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: is this even necessary? */ 218be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (addr) 219be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin strlcpy(out->a2dp_addr, addr, sizeof(out->a2dp_addr)); 220be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_set_sink(out->data, out->a2dp_addr); 221be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 222be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 223be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 224be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 22580e611bd026bf4134abd9e1908b677dc32b8bd91Glenn Kastenstatic bool _out_validate_parms(struct astream_out *out, audio_format_t format, 226be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t chans, uint32_t rate) 227be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 228be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if ((format && (format != out->format)) || 229be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin (chans && (chans != out->channels)) || 230be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin (rate && (rate != out->sample_rate))) 231be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return false; 232be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return true; 233be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 234be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 235be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby_stream_locked(struct astream_out *out) 236be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 237be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret = 0; 238355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int attempts = MAX_WRITE_COMPLETION_ATTEMPTS; 239be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 240be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->standby || !out->data) 241be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 242be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 243355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->standby = true; 244355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* wait for write completion if needed */ 245355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (out->write_busy && attempts--) { 246355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret = pthread_cond_timeout_np(&out->write_cond, 247355afe9a49d429650c955894220caebc1db3b1cfEric Laurent &out->lock, 248355afe9a49d429650c955894220caebc1db3b1cfEric Laurent BUF_WRITE_COMPLETION_TIMEOUT_MS); 2496934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE_IF(ret != 0, "out_standby_stream_locked() wait cond error %d", ret); 250355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 2516934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE_IF(attempts == 0, "out_standby_stream_locked() a2dp_write() would not stop!!!"); 252355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 253999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV_IF(!out->bt_enabled, "Standby skip stop: enabled %d", out->bt_enabled); 254355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->bt_enabled) { 255be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = a2dp_stop(out->data); 256355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 257be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin release_wake_lock(A2DP_WAKE_LOCK_NAME); 258be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 259be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 260be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 261be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 262be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_close_stream_locked(struct astream_out *out) 263be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 264be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 265be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 266be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) { 267999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("%s: calling a2dp_cleanup()", __func__); 268be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_cleanup(out->data); 269be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->data = NULL; 270be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 271be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 272be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 273be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 274be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 275be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby(struct audio_stream *stream) 276be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 277be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 278be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 279be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 280be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 281be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 282be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 283be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 284be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 285be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 286be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 287be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 288be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 289be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 290be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 291be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[32]; 292be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 293be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 294be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(kvpairs); 295be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 296be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 297be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 2983cd3a11758c635ce2415f118f3cdcda186ae681eEric Laurent ret = str_parms_get_str(parms, AUDIO_PARAMETER_A2DP_SINK_ADDRESS, value, sizeof(value)); 299be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 300be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* strlen(00:00:00:00:00:00) == 17 */ 301be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (strlen(value) == 17) { 302be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin strlcpy(out->a2dp_addr, value, sizeof(out->a2dp_addr)); 303be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) 304be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_set_sink(out->data, out->a2dp_addr); 305be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } else 306be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EINVAL; 307be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 308be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 309be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 310be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 311be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 312be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 313be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 314be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic audio_devices_t out_get_device(const struct audio_stream *stream) 315be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 316be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 317be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->device; 318be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 319be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 320be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 321be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_device(struct audio_stream *stream, audio_devices_t device) 322be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 323be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 324be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 325be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!audio_is_a2dp_device(device)) 326be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -EINVAL; 327be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 328be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: if out->device ever starts getting used for anything, need to 329be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * grab the out->lock */ 330be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->device = device; 331be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 332be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 333be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 334be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * out_get_parameters(const struct audio_stream *stream, 335be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const char *keys) 336be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 337be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 338be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 339be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *out_parms; 340be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 341be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[20]; 342be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 343be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 344be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(keys); 345be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_parms = str_parms_create(); 346be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 347be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 348be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 3493cd3a11758c635ce2415f118f3cdcda186ae681eEric Laurent ret = str_parms_get_str(parms, AUDIO_PARAMETER_A2DP_SINK_ADDRESS, value, sizeof(value)); 350be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 3513cd3a11758c635ce2415f118f3cdcda186ae681eEric Laurent str_parms_add_str(out_parms, AUDIO_PARAMETER_A2DP_SINK_ADDRESS, out->a2dp_addr); 352be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 353be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 354be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 355be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str = str_parms_to_str(out_parms); 356be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(out_parms); 357be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 358be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 359be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return str; 360be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 361be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 362355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_available_locked(struct astream_out *out) 363355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 364355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 365355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = out->buf_size - out->buf_frames_ready; 366355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > out->buf_size - out->buf_wr_idx) { 367355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = out->buf_size - out->buf_wr_idx; 368355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 369355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return frames; 370355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 371355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 372355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_ready_locked(struct astream_out *out) 373355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 374355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = out->buf_frames_ready; 375355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 376355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > out->buf_size - out->buf_rd_idx) { 377355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = out->buf_size - out->buf_rd_idx; 378355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 379355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return frames; 380355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 381355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 382355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_wr_idx_locked(struct astream_out *out, size_t frames) 383355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 384355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx += frames; 385355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready += frames; 386355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_wr_idx == out->buf_size) { 387355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx = 0; 388355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 389355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->buf_cond); 390355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 391355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 392355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_rd_idx_locked(struct astream_out *out, size_t frames) 393355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 394355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx += frames; 395355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready -= frames; 396355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_rd_idx == out->buf_size) { 397355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx = 0; 398355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 399355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->buf_cond); 400355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 401355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 402be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 403be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin size_t bytes) 404be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 405be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 406be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 407355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames_total = bytes / sizeof(uint32_t); // always stereo 16 bit 408355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t *buf = (uint32_t *)buffer; 409355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames_written = 0; 410be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 411355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 412be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 413be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!out->bt_enabled || out->suspended) { 414999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("a2dp %s: bluetooth disabled bt_en %d, suspended %d", 415be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled, out->suspended); 416be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -1; 417be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_bt_disabled; 418be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 419be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 420be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->standby) { 421be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME); 422be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->standby = false; 423be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->last_write_time = system_time(); 424355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx = 0; 425355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx = 0; 426355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready = 0; 427be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 428be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 429be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = _out_init_locked(out, NULL); 430355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret < 0) { 431be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_init; 432be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 433be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 434355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 435be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 436355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames_written < frames_total) { 437355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = _out_frames_available_locked(out); 438355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames == 0) { 439355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int ret = pthread_cond_timeout_np(&out->buf_cond, 440355afe9a49d429650c955894220caebc1db3b1cfEric Laurent &out->buf_lock, 441355afe9a49d429650c955894220caebc1db3b1cfEric Laurent BUF_WRITE_AVAILABILITY_TIMEOUT_MS); 442355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret != 0) { 443355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 444355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_write; 445355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 446355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_available_locked(out); 447355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 448355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > frames_total - frames_written) { 449355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = frames_total - frames_written; 450355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 451355afe9a49d429650c955894220caebc1db3b1cfEric Laurent memcpy(out->buf + out->buf_wr_idx, buf + frames_written, frames * sizeof(uint32_t)); 452355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames_written += frames; 453355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_wr_idx_locked(out, frames); 454355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 455355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->standby) { 456355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_write; 457355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 458355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 459be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 460355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 461be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 462be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return bytes; 463be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 464355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* out->lock must be locked and out->buf_lock unlocked when jumping here */ 465be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_write: 466be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_init: 467be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_bt_disabled: 468355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 4697169d82f3c06e91f42226478302150693c5dd56aEric Laurent ALOGV("!!!! write error"); 470be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 471be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 472be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 473be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: simulate audio output timing in case of error?!?! */ 474be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin usleep(out->buffer_duration_us); 475be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 476be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 477be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 478355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 479355afe9a49d429650c955894220caebc1db3b1cfEric Laurentstatic void *_out_buf_thread_func(void *context) 480355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 481355afe9a49d429650c955894220caebc1db3b1cfEric Laurent struct astream_out *out = (struct astream_out *)context; 482355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 483355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 484355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 485355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while(!out->buf_thread_exit) { 486355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames; 487355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 488355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 489355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames && !out->buf_thread_exit) { 490355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int retries = MAX_WRITE_RETRIES; 491355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint64_t now; 492355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t elapsed_us; 493355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 494355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames > 0 && !out->buf_thread_exit) { 495355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int ret; 496355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t buffer_duration_us; 497355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* PCM format is always 16bit stereo */ 498355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t bytes = frames * sizeof(uint32_t); 499355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (bytes > out->buffer_size) { 500355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bytes = out->buffer_size; 501355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 502355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 503355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 504355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->standby) { 505355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* abort and clear all pending frames if standby requested */ 506355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 507355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 508355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 509355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto wait; 510355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 511355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* indicate to out_standby_stream_locked() that a2dp_write() is active */ 512355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->write_busy = true; 513355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 514355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 515355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 516355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret = a2dp_write(out->data, out->buf + out->buf_rd_idx, bytes); 517355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 518355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* clear write_busy condition */ 519355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 520355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 521355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->write_busy = false; 522355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->write_cond); 523355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 524355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 525355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret < 0) { 5266934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("%s: a2dp_write failed (%d)\n", __func__, ret); 527355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* skip pending frames in case of write error */ 528355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 529355afe9a49d429650c955894220caebc1db3b1cfEric Laurent break; 530355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } else if (ret == 0) { 531355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (retries-- == 0) { 532355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* skip pending frames in case of multiple time out */ 533355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 534355afe9a49d429650c955894220caebc1db3b1cfEric Laurent break; 535355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 536355afe9a49d429650c955894220caebc1db3b1cfEric Laurent continue; 537355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 538355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret /= sizeof(uint32_t); 539355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, ret); 540355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames -= ret; 541355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 542355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* XXX: PLEASE FIX ME!!!! */ 543355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 544355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* if A2DP sink runs abnormally fast, sleep a little so that 545355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * audioflinger mixer thread does no spin and starve other threads. */ 546355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* NOTE: It is likely that the A2DP headset is being disconnected */ 547355afe9a49d429650c955894220caebc1db3b1cfEric Laurent now = system_time(); 548355afe9a49d429650c955894220caebc1db3b1cfEric Laurent elapsed_us = (now - out->last_write_time) / 1000UL; 549355afe9a49d429650c955894220caebc1db3b1cfEric Laurent buffer_duration_us = ((ret * 1000) / out->sample_rate) * 1000; 550355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 551355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (elapsed_us < (buffer_duration_us / 4)) { 5527169d82f3c06e91f42226478302150693c5dd56aEric Laurent ALOGV("A2DP sink runs too fast"); 553355afe9a49d429650c955894220caebc1db3b1cfEric Laurent usleep(buffer_duration_us - elapsed_us); 554355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 555355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->last_write_time = now; 556355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 557355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 558355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 559355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 560355afe9a49d429650c955894220caebc1db3b1cfEric Laurentwait: 561355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (!out->buf_thread_exit) { 562355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_wait(&out->buf_cond, &out->buf_lock); 563355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 564355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 565355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 566355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return NULL; 567355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 568355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 569355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 570355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 57121defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 57221defc264075dd8953e7e491a06820e54c964635Eric Laurent{ 57321defc264075dd8953e7e491a06820e54c964635Eric Laurent return 0; 57421defc264075dd8953e7e491a06820e54c964635Eric Laurent} 57521defc264075dd8953e7e491a06820e54c964635Eric Laurent 57621defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 57721defc264075dd8953e7e491a06820e54c964635Eric Laurent{ 57821defc264075dd8953e7e491a06820e54c964635Eric Laurent return 0; 57921defc264075dd8953e7e491a06820e54c964635Eric Laurent} 58021defc264075dd8953e7e491a06820e54c964635Eric Laurent 581be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_bt_enable(struct astream_out *out, bool enable) 582be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 583be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret = 0; 584be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 585be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 586be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled = enable; 587be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!enable) 588be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = out_close_stream_locked(out); 589be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 590be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 591be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 592be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 593be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 594be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_a2dp_suspend(struct astream_out *out, bool suspend) 595be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 596be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 597be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->suspended = suspend; 598be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 599be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 600be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 601be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 602be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 603be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 604635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 605be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open_output_stream(struct audio_hw_device *dev, 60699226bc1a9a6491118a6f30686c53fd406035828Eric Laurent audio_io_handle_t handle, 60799226bc1a9a6491118a6f30686c53fd406035828Eric Laurent audio_devices_t devices, 60899226bc1a9a6491118a6f30686c53fd406035828Eric Laurent audio_output_flags_t flags, 60999226bc1a9a6491118a6f30686c53fd406035828Eric Laurent struct audio_config *config, 610be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out **stream_out) 611635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 612635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurentstatic int adev_open_output_stream(struct audio_hw_device *dev, 613635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent uint32_t devices, audio_format_t *format, 614635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent uint32_t *channels, uint32_t *sample_rate, 615635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent struct audio_stream_out **stream_out) 616635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 617be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 618be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 619be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out; 620be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 621be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 622be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 623be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 624be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* one output stream at a time */ 625be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->output) { 626999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("output exists"); 627be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EBUSY; 628be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_output_exists; 629be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 630be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 631be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out = calloc(1, sizeof(struct astream_out)); 632be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!out) { 633be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -ENOMEM; 634be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_alloc; 635be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 636be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 637be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_init(&out->lock, NULL); 638be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 639be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_sample_rate = out_get_sample_rate; 640be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_sample_rate = out_set_sample_rate; 641be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_buffer_size = out_get_buffer_size; 642be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_channels = out_get_channels; 643be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_format = out_get_format; 644be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_format = out_set_format; 645be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.standby = out_standby; 646be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.dump = out_dump; 647be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_parameters = out_set_parameters; 648be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_parameters = out_get_parameters; 649be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_device = out_set_device; 650be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_device = out_get_device; 65121defc264075dd8953e7e491a06820e54c964635Eric Laurent out->stream.common.add_audio_effect = out_add_audio_effect; 65221defc264075dd8953e7e491a06820e54c964635Eric Laurent out->stream.common.remove_audio_effect = out_remove_audio_effect; 653be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.get_latency = out_get_latency; 654be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.set_volume = out_set_volume; 655be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.write = out_write; 656be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.get_render_position = out_get_render_position; 657be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 658be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->sample_rate = 44100; 659be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->buffer_size = 512 * 20; 660be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->channels = AUDIO_CHANNEL_OUT_STEREO; 661be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->format = AUDIO_FORMAT_PCM_16_BIT; 662be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 663be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->fd = -1; 664be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->device = devices; 665be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled = adev->bt_enabled; 666be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->suspended = adev->suspended; 667be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 668be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* for now, buffer_duration_us is precalculated and never changed. 669be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * if the sample rate or the format ever changes on the fly, we'd have 670be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * to recalculate this */ 671be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->buffer_duration_us = ((out->buffer_size * 1000 ) / 672be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_stream_frame_size(&out->stream.common) / 673be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->sample_rate) * 1000; 674635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 67599226bc1a9a6491118a6f30686c53fd406035828Eric Laurent if (!_out_validate_parms(out, config->format, 67699226bc1a9a6491118a6f30686c53fd406035828Eric Laurent config->channel_mask, 677635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent config->sample_rate)) 678635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 679635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent if (!_out_validate_parms(out, format ? *format : 0, 680635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent channels ? *channels : 0, 681635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent sample_rate ? *sample_rate : 0)) 682635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 683635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent { 684999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("invalid parameters"); 685be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EINVAL; 686be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_validate_parms; 687be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 688be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 689355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int err = pthread_create(&out->buf_thread, (const pthread_attr_t *) NULL, _out_buf_thread_func, out); 690355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (err != 0) { 691355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_validate_parms; 692355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 693355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 694355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* PCM format is always 16bit, stereo */ 695355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_size = (out->buffer_size * BUF_NUM_PERIODS) / sizeof(int32_t); 696355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf = (uint32_t *)malloc(out->buf_size * sizeof(int32_t)); 697355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (!out->buf) { 698355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_validate_parms; 699355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 700355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 701be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: check return code? */ 702be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->bt_enabled) 703be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin _out_init_locked(out, "00:00:00:00:00:00"); 704be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 705be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->output = out; 706be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 707635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 70899226bc1a9a6491118a6f30686c53fd406035828Eric Laurent config->format = out->format; 70999226bc1a9a6491118a6f30686c53fd406035828Eric Laurent config->channel_mask = out->channels; 71099226bc1a9a6491118a6f30686c53fd406035828Eric Laurent config->sample_rate = out->sample_rate; 711635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 712635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent if (format) 713635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent *format = out->format; 714635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent if (channels) 715635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent *channels = out->channels; 716635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent if (sample_rate) 717635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent *sample_rate = out->sample_rate; 718635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 719be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 720be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 721be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *stream_out = &out->stream; 722be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 723be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 724be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 725be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_validate_parms: 726be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(out); 727be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_alloc: 728be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_output_exists: 729be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 730be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *stream_out = NULL; 731be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 732be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 733be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 734be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/* needs the adev->lock held */ 735be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream_locked(struct adev_a2dp *dev, 736be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *stream) 737be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 738be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 739be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 740be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 741be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* invalid stream? */ 742be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!adev->output || adev->output != out) { 7436934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("%s: unknown stream %p (ours is %p)", __func__, out, adev->output); 744be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return; 745be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 746be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 747be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 748355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* out_write() must not be executed from now on */ 749355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->bt_enabled = false; 750be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_close_stream_locked(out); 751be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 752355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_thread) { 753355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 754355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_thread_exit = true; 755355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_broadcast(&out->buf_cond); 756355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 757355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_join(out->buf_thread, (void **) NULL); 758355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_destroy(&out->buf_cond); 759355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_destroy(&out->buf_lock); 760355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 761355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf) { 762355afe9a49d429650c955894220caebc1db3b1cfEric Laurent free(out->buf); 763355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 764be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 765be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->output = NULL; 766be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(out); 767be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 768be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 769be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream(struct audio_hw_device *dev, 770be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out *stream) 771be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 772be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 773be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 774be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 775be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 776be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev_close_output_stream_locked(adev, out); 777be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 778be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 779be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 780be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 781be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 782be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 783be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 784be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 785be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[8]; 786be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 787be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 788be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(kvpairs); 789be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 790be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 791be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 792be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value, 793be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin sizeof(value)); 794be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 795be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled = !strcmp(value, "true"); 796eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent if (adev->output) 797eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent _out_bt_enable(adev->output, adev->bt_enabled); 798be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 799be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 800be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value)); 801be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 802be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->suspended = !strcmp(value, "true"); 803eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent if (adev->output) 804eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent _out_a2dp_suspend(adev->output, adev->suspended); 805be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 806be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 807be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 808be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 809be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 810be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 811be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 812be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 813be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 814be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * adev_get_parameters(const struct audio_hw_device *dev, 815be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const char *keys) 816be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 817be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 818be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 819be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *out_parms; 820be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 821be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[8]; 822be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 823be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 824be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(keys); 825be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_parms = str_parms_create(); 826be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 827be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 828be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 829be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value, 830be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin sizeof(value)); 831be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 832be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_add_str(out_parms, BLUETOOOTH_ENABLED_PARM, 833be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled ? "true" : "false"); 834be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 835be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value)); 836be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 837be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_add_str(out_parms, A2DP_SUSPENDED_PARM, 838be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->suspended ? "true" : "false"); 839be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 840be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 841be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 842be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str = str_parms_to_str(out_parms); 843be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(out_parms); 844be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 845be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 846be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return str; 847be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 848be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 849be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_init_check(const struct audio_hw_device *dev) 850be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 851be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 852be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 853be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 854be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 855be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 856be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 857be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 858be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 859be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume) 860be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 861be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 862be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 863be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 864d0cbf948b7c9bdc2a5a0134ea04ffcb0c825218eGlenn Kastenstatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 865be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 866be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* TODO: do we care for the mode? */ 867be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 868be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 869be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 870be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 871be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 872be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 873be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 874be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 875be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 876be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 877be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 878be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 879be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 880635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 881be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 88299226bc1a9a6491118a6f30686c53fd406035828Eric Laurent const struct audio_config *config) 883635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 884635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurentstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 885635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent uint32_t sample_rate, audio_format_t format, 886635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent int channel_count) 887635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 888be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 889be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* no input */ 890be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 891be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 892be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 893635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 89499226bc1a9a6491118a6f30686c53fd406035828Eric Laurentstatic int adev_open_input_stream(struct audio_hw_device *dev, 89599226bc1a9a6491118a6f30686c53fd406035828Eric Laurent audio_io_handle_t handle, 89699226bc1a9a6491118a6f30686c53fd406035828Eric Laurent audio_devices_t devices, 89799226bc1a9a6491118a6f30686c53fd406035828Eric Laurent struct audio_config *config, 898be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_in **stream_in) 899635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 900635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurentstatic int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices, 901635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent audio_format_t *format, uint32_t *channels, 902635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent uint32_t *sample_rate, 903635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent audio_in_acoustics_t acoustics, 904635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent struct audio_stream_in **stream_in) 905635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 906be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 907be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 908be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 909be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 910be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_input_stream(struct audio_hw_device *dev, 911be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_in *in) 912be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 913be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return; 914be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 915be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 916be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_dump(const audio_hw_device_t *device, int fd) 917be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 918be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 919be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 920be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 921be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_close(hw_device_t *device) 922be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 923be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)device; 924be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 925be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 926be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->output) 927be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev_close_output_stream_locked(adev, adev->output); 928be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 929be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(adev); 930be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 931be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 932be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 933be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 934be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t adev_get_supported_devices(const struct audio_hw_device *dev) 935be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 936be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return AUDIO_DEVICE_OUT_ALL_A2DP; 937be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 938be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 939be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open(const hw_module_t* module, const char* name, 940be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin hw_device_t** device) 941be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 942be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev; 943be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 944be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 945be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 946be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -EINVAL; 947be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 948be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev = calloc(1, sizeof(struct adev_a2dp)); 949be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!adev) 950be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOMEM; 951be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 952be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled = true; 953eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent adev->suspended = false; 954be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_init(&adev->lock, NULL); 955eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent adev->output = NULL; 956be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 957be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.tag = HARDWARE_DEVICE_TAG; 958635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_DEVICE_API_VERSION_1_0 95999226bc1a9a6491118a6f30686c53fd406035828Eric Laurent adev->device.common.version = AUDIO_DEVICE_API_VERSION_1_0; 960635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 961635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent adev->device.common.version = 0; 962635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 963be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.module = (struct hw_module_t *) module; 964be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.close = adev_close; 965be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 966be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_supported_devices = adev_get_supported_devices; 967be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.init_check = adev_init_check; 968be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_voice_volume = adev_set_voice_volume; 969be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_master_volume = adev_set_master_volume; 970be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_mode = adev_set_mode; 971be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_mic_mute = adev_set_mic_mute; 972be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_mic_mute = adev_get_mic_mute; 973be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_parameters = adev_set_parameters; 974be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_parameters = adev_get_parameters; 975be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_input_buffer_size = adev_get_input_buffer_size; 976be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.open_output_stream = adev_open_output_stream; 977be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.close_output_stream = adev_close_output_stream; 978be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.open_input_stream = adev_open_input_stream; 979be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.close_input_stream = adev_close_input_stream; 980be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.dump = adev_dump; 981be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 982be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *device = &adev->device.common; 983be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 984be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 985be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 986be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_str_parms_create: 987be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(adev); 988be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 989be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 990be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 991be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic struct hw_module_methods_t hal_module_methods = { 992be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .open = adev_open, 993be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 994be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 995be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct audio_module HAL_MODULE_INFO_SYM = { 996be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .common = { 997be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .tag = HARDWARE_MODULE_TAG, 998635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#ifdef AUDIO_MODULE_API_VERSION_0_1 99999226bc1a9a6491118a6f30686c53fd406035828Eric Laurent .module_api_version = AUDIO_MODULE_API_VERSION_0_1, 100099226bc1a9a6491118a6f30686c53fd406035828Eric Laurent .hal_api_version = HARDWARE_HAL_API_VERSION, 1001635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#else 1002635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent .version_major = 1, 1003635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent .version_minor = 0, 1004635699a5d1761b3ed9572537fc620e0eb05bf500Eric Laurent#endif 1005be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .id = AUDIO_HARDWARE_MODULE_ID, 1006be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .name = "A2DP Audio HW HAL", 1007be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .author = "The Android Open Source Project", 1008be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .methods = &hal_module_methods, 1009be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin }, 1010be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 1011be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 1012be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 1013