android_audio_hw.c revision 6934b76075fabbd7a1f542b3000b250f4a589492
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 39be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_WAKE_LOCK_NAME "A2dpOutputStream" 40be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define MAX_WRITE_RETRIES 5 41be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 42be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_SUSPENDED_PARM "A2dpSuspended" 43be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define BLUETOOOTH_ENABLED_PARM "bluetooth_enabled" 44be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 45be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define OUT_SINK_ADDR_PARM "a2dp_sink_address" 46be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 47355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* number of periods in pcm buffer (one period corresponds to buffer size reported to audio flinger 48355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * by out_get_buffer_size() */ 49355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_NUM_PERIODS 6 50355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_standby_stream_locked() for 2dp_write() to complete */ 51355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_WRITE_COMPLETION_TIMEOUT_MS 5000 52355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_write() for frames to be available in in write thread buffer */ 5305675015d13729f7da5bf32c88264c68e02d6028Eric Laurent#define BUF_WRITE_AVAILABILITY_TIMEOUT_MS 5000 54355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum number of attempts to wait for a write completion in out_standby_stream_locked() */ 55355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define MAX_WRITE_COMPLETION_ATTEMPTS 5 56355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 57355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* NOTE: there are 2 mutexes used by the a2dp output stream. 58355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * - lock: protects all calls to a2dp lib functions (a2dp_stop(), a2dp_cleanup()...). 59355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * One exception is a2dp_write() which is also protected by the flag write_busy. This is because 60355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * out_write() cannot block waiting for a2dp_write() to complete because this function 61355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * can sleep to throttle the A2DP bit rate. 62355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * This flag is always set/reset and tested with "lock" mutex held. 63355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * - buf_lock: protects access to pcm buffer read and write indexes. 64355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * 65355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * The locking order is always as follows: 66355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * buf_lock -> lock 67355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * 68355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * If you need to hold the adev_a2dp->lock AND the astream_out->lock or astream_out->buf_lock, 69355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * you MUST take adev_a2dp lock first!! 70be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin */ 71be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 72be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out; 73be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct adev_a2dp { 74be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_hw_device device; 75be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 76be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_mode_t mode; 77be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool bt_enabled; 78be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool suspended; 79be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 80be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_t lock; 81be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 82be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *output; 83be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 84be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 85be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out { 86be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out stream; 87be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 88be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t sample_rate; 89be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin size_t buffer_size; 90be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t channels; 91be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int format; 92be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 93be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int fd; 94be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool standby; 95be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int start_count; 96be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int retry_count; 97be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin void* data; 98be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 99355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_t lock; /* see NOTE on mutex locking order above */ 100be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 101be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_devices_t device; 102be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint64_t last_write_time; 103be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t buffer_duration_us; 104be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 105be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool bt_enabled; 106be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin bool suspended; 107be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char a2dp_addr[20]; 108355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 109355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t *buf; /* pcm buffer between audioflinger thread and write thread*/ 110355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_size; /* size of pcm buffer in frames */ 111355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_rd_idx; /* read index in pcm buffer, in frames*/ 112355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_wr_idx; /* write index in pcm buffer, in frames */ 113355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t buf_frames_ready; /* number of frames ready for writing to a2dp sink */ 114355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_t buf_lock; /* mutex protecting read and write indexes */ 115355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* see NOTE on mutex locking order above */ 116355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_t buf_cond; /* condition signaling data write/read to/from pcm buffer */ 117355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_t buf_thread; /* thread reading data from buffer and writing to a2dp sink*/ 118355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bool buf_thread_exit; /* flag requesting write thread exit */ 119355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bool write_busy; /* indicates that a write to a2dp sink is in progress and that 120355afe9a49d429650c955894220caebc1db3b1cfEric Laurent standby must wait for this flag to be cleared by write thread */ 121355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_t write_cond; /* condition associated with write_busy flag */ 122be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 123be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 124be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint64_t system_time(void) 125be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 126be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct timespec t; 127be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 128be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin t.tv_sec = t.tv_nsec = 0; 129be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin clock_gettime(CLOCK_MONOTONIC, &t); 130be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 131be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return t.tv_sec*1000000000LL + t.tv_nsec; 132be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 133be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 134be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/** audio_stream_out implementation **/ 135be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_sample_rate(const struct audio_stream *stream) 136be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 137be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 138be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->sample_rate; 139be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 140be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 141be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 142be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 143be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 144be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 1456934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 146be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 147be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 148be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 149be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t out_get_buffer_size(const struct audio_stream *stream) 150be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 151be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 152be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->buffer_size; 153be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 154be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 155be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_channels(const struct audio_stream *stream) 156be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 157be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 158be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->channels; 159be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 160be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 161be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_get_format(const struct audio_stream *stream) 162be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 163be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 164be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->format; 165be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 166be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 167be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_format(struct audio_stream *stream, int format) 168be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 169be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 1706934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__); 171be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 172be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 173be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 174be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_dump(const struct audio_stream *stream, int fd) 175be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 176be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 177be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 178be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 179be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_latency(const struct audio_stream_out *stream) 180be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 181be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 182be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 183be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return (out->buffer_duration_us / 1000) + 200; 184be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 185be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 186be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_volume(struct audio_stream_out *stream, float left, 187be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin float right) 188be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 189be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 190be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 191be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 192be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_get_render_position(const struct audio_stream_out *stream, 193be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t *dsp_frames) 194be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 195be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 196be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 197be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 198be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_init_locked(struct astream_out *out, const char *addr) 199be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 200be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 201be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 202be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) 203be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 204be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 205be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: shouldn't this use the sample_rate/channel_count from 'out'? */ 206be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = a2dp_init(44100, 2, &out->data); 207be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret < 0) { 2086934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("a2dp_init failed err: %d\n", ret); 209be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->data = NULL; 210be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 211be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 212be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 213be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: is this even necessary? */ 214be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (addr) 215be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin strlcpy(out->a2dp_addr, addr, sizeof(out->a2dp_addr)); 216be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_set_sink(out->data, out->a2dp_addr); 217be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 218be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 219be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 220be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 221be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic bool _out_validate_parms(struct astream_out *out, int format, 222be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t chans, uint32_t rate) 223be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 224be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if ((format && (format != out->format)) || 225be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin (chans && (chans != out->channels)) || 226be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin (rate && (rate != out->sample_rate))) 227be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return false; 228be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return true; 229be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 230be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 231be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby_stream_locked(struct astream_out *out) 232be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 233be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret = 0; 234355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int attempts = MAX_WRITE_COMPLETION_ATTEMPTS; 235be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 236be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->standby || !out->data) 237be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 238be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 239355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->standby = true; 240355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* wait for write completion if needed */ 241355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (out->write_busy && attempts--) { 242355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret = pthread_cond_timeout_np(&out->write_cond, 243355afe9a49d429650c955894220caebc1db3b1cfEric Laurent &out->lock, 244355afe9a49d429650c955894220caebc1db3b1cfEric Laurent BUF_WRITE_COMPLETION_TIMEOUT_MS); 2456934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE_IF(ret != 0, "out_standby_stream_locked() wait cond error %d", ret); 246355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 2476934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE_IF(attempts == 0, "out_standby_stream_locked() a2dp_write() would not stop!!!"); 248355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 249999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV_IF(!out->bt_enabled, "Standby skip stop: enabled %d", out->bt_enabled); 250355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->bt_enabled) { 251be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = a2dp_stop(out->data); 252355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 253be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin release_wake_lock(A2DP_WAKE_LOCK_NAME); 254be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 255be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 256be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 257be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 258be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_close_stream_locked(struct astream_out *out) 259be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 260be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 261be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 262be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) { 263999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("%s: calling a2dp_cleanup()", __func__); 264be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_cleanup(out->data); 265be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->data = NULL; 266be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 267be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 268be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 269be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 270be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 271be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby(struct audio_stream *stream) 272be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 273be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 274be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 275be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 276be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 277be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 278be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 279be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 280be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 281be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 282be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 283be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 284be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 285be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 286be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 287be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[32]; 288be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 289be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 290be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(kvpairs); 291be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 292be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 293be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 294be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value)); 295be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 296be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* strlen(00:00:00:00:00:00) == 17 */ 297be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (strlen(value) == 17) { 298be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin strlcpy(out->a2dp_addr, value, sizeof(out->a2dp_addr)); 299be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->data) 300be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin a2dp_set_sink(out->data, out->a2dp_addr); 301be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } else 302be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EINVAL; 303be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 304be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 305be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 306be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 307be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 308be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 309be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 310be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic audio_devices_t out_get_device(const struct audio_stream *stream) 311be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 312be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const struct astream_out *out = (const struct astream_out *)stream; 313be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return out->device; 314be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 315be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 316be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 317be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_device(struct audio_stream *stream, audio_devices_t device) 318be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 319be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 320be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 321be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!audio_is_a2dp_device(device)) 322be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -EINVAL; 323be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 324be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: if out->device ever starts getting used for anything, need to 325be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * grab the out->lock */ 326be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->device = device; 327be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 328be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 329be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 330be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * out_get_parameters(const struct audio_stream *stream, 331be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const char *keys) 332be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 333be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 334be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 335be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *out_parms; 336be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 337be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[20]; 338be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 339be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 340be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(keys); 341be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_parms = str_parms_create(); 342be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 343be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 344be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 345be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value)); 346be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 347be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_add_str(out_parms, OUT_SINK_ADDR_PARM, out->a2dp_addr); 348be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 349be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 350be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 351be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str = str_parms_to_str(out_parms); 352be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(out_parms); 353be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 354be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 355be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return str; 356be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 357be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 358355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_available_locked(struct astream_out *out) 359355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 360355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 361355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = out->buf_size - out->buf_frames_ready; 362355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > out->buf_size - out->buf_wr_idx) { 363355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = out->buf_size - out->buf_wr_idx; 364355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 365355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return frames; 366355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 367355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 368355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_ready_locked(struct astream_out *out) 369355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 370355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = out->buf_frames_ready; 371355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 372355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > out->buf_size - out->buf_rd_idx) { 373355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = out->buf_size - out->buf_rd_idx; 374355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 375355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return frames; 376355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 377355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 378355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_wr_idx_locked(struct astream_out *out, size_t frames) 379355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 380355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx += frames; 381355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready += frames; 382355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_wr_idx == out->buf_size) { 383355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx = 0; 384355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 385355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->buf_cond); 386355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 387355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 388355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_rd_idx_locked(struct astream_out *out, size_t frames) 389355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 390355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx += frames; 391355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready -= frames; 392355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_rd_idx == out->buf_size) { 393355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx = 0; 394355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 395355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->buf_cond); 396355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 397355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 398be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 399be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin size_t bytes) 400be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 401be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 402be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 403355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames_total = bytes / sizeof(uint32_t); // always stereo 16 bit 404355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t *buf = (uint32_t *)buffer; 405355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames_written = 0; 406be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 407355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 408be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 409be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!out->bt_enabled || out->suspended) { 410999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("a2dp %s: bluetooth disabled bt_en %d, suspended %d", 411be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled, out->suspended); 412be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -1; 413be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_bt_disabled; 414be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 415be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 416be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (out->standby) { 417be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME); 418be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->standby = false; 419be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->last_write_time = system_time(); 420355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_rd_idx = 0; 421355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_wr_idx = 0; 422355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_frames_ready = 0; 423be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 424be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 425be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = _out_init_locked(out, NULL); 426355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret < 0) { 427be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_init; 428be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 429be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 430355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 431be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 432355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames_written < frames_total) { 433355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames = _out_frames_available_locked(out); 434355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames == 0) { 435355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int ret = pthread_cond_timeout_np(&out->buf_cond, 436355afe9a49d429650c955894220caebc1db3b1cfEric Laurent &out->buf_lock, 437355afe9a49d429650c955894220caebc1db3b1cfEric Laurent BUF_WRITE_AVAILABILITY_TIMEOUT_MS); 438355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret != 0) { 439355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 440355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_write; 441355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 442355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_available_locked(out); 443355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 444355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (frames > frames_total - frames_written) { 445355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = frames_total - frames_written; 446355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 447355afe9a49d429650c955894220caebc1db3b1cfEric Laurent memcpy(out->buf + out->buf_wr_idx, buf + frames_written, frames * sizeof(uint32_t)); 448355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames_written += frames; 449355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_wr_idx_locked(out, frames); 450355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 451355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->standby) { 452355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_write; 453355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 454355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 455be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 456355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 457be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 458be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return bytes; 459be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 460355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* out->lock must be locked and out->buf_lock unlocked when jumping here */ 461be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_write: 462be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_init: 463be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_bt_disabled: 464355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 4657169d82f3c06e91f42226478302150693c5dd56aEric Laurent ALOGV("!!!! write error"); 466be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 467be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 468be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 469be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: simulate audio output timing in case of error?!?! */ 470be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin usleep(out->buffer_duration_us); 471be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 472be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 473be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 474355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 475355afe9a49d429650c955894220caebc1db3b1cfEric Laurentstatic void *_out_buf_thread_func(void *context) 476355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{ 477355afe9a49d429650c955894220caebc1db3b1cfEric Laurent struct astream_out *out = (struct astream_out *)context; 478355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 479355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 480355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 481355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while(!out->buf_thread_exit) { 482355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t frames; 483355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 484355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 485355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames && !out->buf_thread_exit) { 486355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int retries = MAX_WRITE_RETRIES; 487355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint64_t now; 488355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t elapsed_us; 489355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 490355afe9a49d429650c955894220caebc1db3b1cfEric Laurent while (frames > 0 && !out->buf_thread_exit) { 491355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int ret; 492355afe9a49d429650c955894220caebc1db3b1cfEric Laurent uint32_t buffer_duration_us; 493355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* PCM format is always 16bit stereo */ 494355afe9a49d429650c955894220caebc1db3b1cfEric Laurent size_t bytes = frames * sizeof(uint32_t); 495355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (bytes > out->buffer_size) { 496355afe9a49d429650c955894220caebc1db3b1cfEric Laurent bytes = out->buffer_size; 497355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 498355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 499355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 500355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->standby) { 501355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* abort and clear all pending frames if standby requested */ 502355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 503355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 504355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 505355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto wait; 506355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 507355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* indicate to out_standby_stream_locked() that a2dp_write() is active */ 508355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->write_busy = true; 509355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 510355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 511355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 512355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret = a2dp_write(out->data, out->buf + out->buf_rd_idx, bytes); 513355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 514355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* clear write_busy condition */ 515355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 516355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->lock); 517355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->write_busy = false; 518355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_signal(&out->write_cond); 519355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->lock); 520355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 521355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (ret < 0) { 5226934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("%s: a2dp_write failed (%d)\n", __func__, ret); 523355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* skip pending frames in case of write error */ 524355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 525355afe9a49d429650c955894220caebc1db3b1cfEric Laurent break; 526355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } else if (ret == 0) { 527355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (retries-- == 0) { 528355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* skip pending frames in case of multiple time out */ 529355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, frames); 530355afe9a49d429650c955894220caebc1db3b1cfEric Laurent break; 531355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 532355afe9a49d429650c955894220caebc1db3b1cfEric Laurent continue; 533355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 534355afe9a49d429650c955894220caebc1db3b1cfEric Laurent ret /= sizeof(uint32_t); 535355afe9a49d429650c955894220caebc1db3b1cfEric Laurent _out_inc_rd_idx_locked(out, ret); 536355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames -= ret; 537355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 538355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* XXX: PLEASE FIX ME!!!! */ 539355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 540355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* if A2DP sink runs abnormally fast, sleep a little so that 541355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * audioflinger mixer thread does no spin and starve other threads. */ 542355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* NOTE: It is likely that the A2DP headset is being disconnected */ 543355afe9a49d429650c955894220caebc1db3b1cfEric Laurent now = system_time(); 544355afe9a49d429650c955894220caebc1db3b1cfEric Laurent elapsed_us = (now - out->last_write_time) / 1000UL; 545355afe9a49d429650c955894220caebc1db3b1cfEric Laurent buffer_duration_us = ((ret * 1000) / out->sample_rate) * 1000; 546355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 547355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (elapsed_us < (buffer_duration_us / 4)) { 5487169d82f3c06e91f42226478302150693c5dd56aEric Laurent ALOGV("A2DP sink runs too fast"); 549355afe9a49d429650c955894220caebc1db3b1cfEric Laurent usleep(buffer_duration_us - elapsed_us); 550355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 551355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->last_write_time = now; 552355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 553355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 554355afe9a49d429650c955894220caebc1db3b1cfEric Laurent frames = _out_frames_ready_locked(out); 555355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 556355afe9a49d429650c955894220caebc1db3b1cfEric Laurentwait: 557355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (!out->buf_thread_exit) { 558355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_wait(&out->buf_cond, &out->buf_lock); 559355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 560355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 561355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 562355afe9a49d429650c955894220caebc1db3b1cfEric Laurent return NULL; 563355afe9a49d429650c955894220caebc1db3b1cfEric Laurent} 564355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 565355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 566355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 56721defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 56821defc264075dd8953e7e491a06820e54c964635Eric Laurent{ 56921defc264075dd8953e7e491a06820e54c964635Eric Laurent return 0; 57021defc264075dd8953e7e491a06820e54c964635Eric Laurent} 57121defc264075dd8953e7e491a06820e54c964635Eric Laurent 57221defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 57321defc264075dd8953e7e491a06820e54c964635Eric Laurent{ 57421defc264075dd8953e7e491a06820e54c964635Eric Laurent return 0; 57521defc264075dd8953e7e491a06820e54c964635Eric Laurent} 57621defc264075dd8953e7e491a06820e54c964635Eric Laurent 577be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_bt_enable(struct astream_out *out, bool enable) 578be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 579be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret = 0; 580be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 581be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 582be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled = enable; 583be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!enable) 584be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = out_close_stream_locked(out); 585be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 586be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 587be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 588be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 589be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 590be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_a2dp_suspend(struct astream_out *out, bool suspend) 591be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 592be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 593be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->suspended = suspend; 594be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_standby_stream_locked(out); 595be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 596be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 597be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 598be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 599be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 600be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open_output_stream(struct audio_hw_device *dev, 601be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t devices, int *format, 602be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t *channels, uint32_t *sample_rate, 603be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out **stream_out) 604be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 605be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 606be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out; 607be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 608be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 609be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 610be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 611be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* one output stream at a time */ 612be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->output) { 613999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("output exists"); 614be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EBUSY; 615be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_output_exists; 616be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 617be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 618be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out = calloc(1, sizeof(struct astream_out)); 619be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!out) { 620be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -ENOMEM; 621be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_alloc; 622be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 623be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 624be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_init(&out->lock, NULL); 625be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 626be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_sample_rate = out_get_sample_rate; 627be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_sample_rate = out_set_sample_rate; 628be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_buffer_size = out_get_buffer_size; 629be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_channels = out_get_channels; 630be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_format = out_get_format; 631be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_format = out_set_format; 632be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.standby = out_standby; 633be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.dump = out_dump; 634be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_parameters = out_set_parameters; 635be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_parameters = out_get_parameters; 636be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.set_device = out_set_device; 637be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.common.get_device = out_get_device; 63821defc264075dd8953e7e491a06820e54c964635Eric Laurent out->stream.common.add_audio_effect = out_add_audio_effect; 63921defc264075dd8953e7e491a06820e54c964635Eric Laurent out->stream.common.remove_audio_effect = out_remove_audio_effect; 640be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.get_latency = out_get_latency; 641be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.set_volume = out_set_volume; 642be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.write = out_write; 643be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->stream.get_render_position = out_get_render_position; 644be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 645be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->sample_rate = 44100; 646be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->buffer_size = 512 * 20; 647be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->channels = AUDIO_CHANNEL_OUT_STEREO; 648be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->format = AUDIO_FORMAT_PCM_16_BIT; 649be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 650be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->fd = -1; 651be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->device = devices; 652be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->bt_enabled = adev->bt_enabled; 653be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->suspended = adev->suspended; 654be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 655be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* for now, buffer_duration_us is precalculated and never changed. 656be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * if the sample rate or the format ever changes on the fly, we'd have 657be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin * to recalculate this */ 658be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->buffer_duration_us = ((out->buffer_size * 1000 ) / 659be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_stream_frame_size(&out->stream.common) / 660be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out->sample_rate) * 1000; 661be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!_out_validate_parms(out, format ? *format : 0, 662be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin channels ? *channels : 0, 663be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin sample_rate ? *sample_rate : 0)) { 664999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block ALOGV("invalid parameters"); 665be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = -EINVAL; 666be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin goto err_validate_parms; 667be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 668be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 669355afe9a49d429650c955894220caebc1db3b1cfEric Laurent int err = pthread_create(&out->buf_thread, (const pthread_attr_t *) NULL, _out_buf_thread_func, out); 670355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (err != 0) { 671355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_validate_parms; 672355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 673355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 674355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* PCM format is always 16bit, stereo */ 675355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_size = (out->buffer_size * BUF_NUM_PERIODS) / sizeof(int32_t); 676355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf = (uint32_t *)malloc(out->buf_size * sizeof(int32_t)); 677355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (!out->buf) { 678355afe9a49d429650c955894220caebc1db3b1cfEric Laurent goto err_validate_parms; 679355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 680355afe9a49d429650c955894220caebc1db3b1cfEric Laurent 681be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* XXX: check return code? */ 682be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->bt_enabled) 683be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin _out_init_locked(out, "00:00:00:00:00:00"); 684be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 685be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->output = out; 686be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 687be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (format) 688be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *format = out->format; 689be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (channels) 690be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *channels = out->channels; 691be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (sample_rate) 692be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *sample_rate = out->sample_rate; 693be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 694be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 695be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 696be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *stream_out = &out->stream; 697be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 698be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 699be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 700be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_validate_parms: 701be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(out); 702be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_alloc: 703be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_output_exists: 704be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 705be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *stream_out = NULL; 706be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 707be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 708be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 709be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/* needs the adev->lock held */ 710be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream_locked(struct adev_a2dp *dev, 711be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *stream) 712be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 713be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 714be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 715be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 716be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* invalid stream? */ 717be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!adev->output || adev->output != out) { 7186934b76075fabbd7a1f542b3000b250f4a589492Steve Block ALOGE("%s: unknown stream %p (ours is %p)", __func__, out, adev->output); 719be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return; 720be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 721be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 722be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&out->lock); 723355afe9a49d429650c955894220caebc1db3b1cfEric Laurent /* out_write() must not be executed from now on */ 724355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->bt_enabled = false; 725be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_close_stream_locked(out); 726be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&out->lock); 727355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf_thread) { 728355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_lock(&out->buf_lock); 729355afe9a49d429650c955894220caebc1db3b1cfEric Laurent out->buf_thread_exit = true; 730355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_broadcast(&out->buf_cond); 731355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_unlock(&out->buf_lock); 732355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_join(out->buf_thread, (void **) NULL); 733355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_cond_destroy(&out->buf_cond); 734355afe9a49d429650c955894220caebc1db3b1cfEric Laurent pthread_mutex_destroy(&out->buf_lock); 735355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 736355afe9a49d429650c955894220caebc1db3b1cfEric Laurent if (out->buf) { 737355afe9a49d429650c955894220caebc1db3b1cfEric Laurent free(out->buf); 738355afe9a49d429650c955894220caebc1db3b1cfEric Laurent } 739be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 740be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->output = NULL; 741be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(out); 742be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 743be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 744be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream(struct audio_hw_device *dev, 745be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_out *stream) 746be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 747be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 748be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct astream_out *out = (struct astream_out *)stream; 749be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 750be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 751be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev_close_output_stream_locked(adev, out); 752be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 753be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 754be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 755be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 756be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 757be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 758be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 759be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 760be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[8]; 761be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 762be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 763be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(kvpairs); 764be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 765be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 766be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 767be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value, 768be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin sizeof(value)); 769be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 770be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled = !strcmp(value, "true"); 771eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent if (adev->output) 772eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent _out_bt_enable(adev->output, adev->bt_enabled); 773be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 774be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 775be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value)); 776be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) { 777be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->suspended = !strcmp(value, "true"); 778eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent if (adev->output) 779eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent _out_a2dp_suspend(adev->output, adev->suspended); 780be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin } 781be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 782be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 783be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 784be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 785be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 786be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 787be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 788be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 789be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * adev_get_parameters(const struct audio_hw_device *dev, 790be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin const char *keys) 791be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 792be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)dev; 793be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *parms; 794be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct str_parms *out_parms; 795be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char *str; 796be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin char value[8]; 797be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 798be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 799be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin parms = str_parms_create_str(keys); 800be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin out_parms = str_parms_create(); 801be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 802be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 803be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 804be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value, 805be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin sizeof(value)); 806be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 807be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_add_str(out_parms, BLUETOOOTH_ENABLED_PARM, 808be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled ? "true" : "false"); 809be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 810be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value)); 811be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (ret >= 0) 812be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_add_str(out_parms, A2DP_SUSPENDED_PARM, 813be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->suspended ? "true" : "false"); 814be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 815be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 816be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 817be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str = str_parms_to_str(out_parms); 818be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(out_parms); 819be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin str_parms_destroy(parms); 820be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 821be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return str; 822be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 823be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 824be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_init_check(const struct audio_hw_device *dev) 825be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 826be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 827be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 828be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 829be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 830be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 831be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 832be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 833be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 834be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume) 835be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 836be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 837be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 838be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 839be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_mode(struct audio_hw_device *dev, int mode) 840be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 841be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* TODO: do we care for the mode? */ 842be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 843be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 844be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 845be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 846be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 847be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 848be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 849be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 850be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 851be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 852be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 853be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 854be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 855be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 856be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t sample_rate, int format, 857be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int channel_count) 858be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 859be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin /* no input */ 860be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 861be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 862be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 863be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices, 864be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int *format, uint32_t *channels, 865be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin uint32_t *sample_rate, 866be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin audio_in_acoustics_t acoustics, 867be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_in **stream_in) 868be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 869be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOSYS; 870be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 871be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 872be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_input_stream(struct audio_hw_device *dev, 873be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct audio_stream_in *in) 874be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 875be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return; 876be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 877be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 878be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_dump(const audio_hw_device_t *device, int fd) 879be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 880be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 881be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 882be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 883be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_close(hw_device_t *device) 884be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 885be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev = (struct adev_a2dp *)device; 886be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 887be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_lock(&adev->lock); 888be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (adev->output) 889be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev_close_output_stream_locked(adev, adev->output); 890be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_unlock(&adev->lock); 891be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(adev); 892be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 893be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 894be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 895be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 896be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t adev_get_supported_devices(const struct audio_hw_device *dev) 897be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 898be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return AUDIO_DEVICE_OUT_ALL_A2DP; 899be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 900be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 901be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open(const hw_module_t* module, const char* name, 902be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin hw_device_t** device) 903be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{ 904be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin struct adev_a2dp *adev; 905be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin int ret; 906be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 907be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 908be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -EINVAL; 909be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 910be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev = calloc(1, sizeof(struct adev_a2dp)); 911be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin if (!adev) 912be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return -ENOMEM; 913be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 914be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->bt_enabled = true; 915eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent adev->suspended = false; 916be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin pthread_mutex_init(&adev->lock, NULL); 917eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent adev->output = NULL; 918be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 919be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.tag = HARDWARE_DEVICE_TAG; 920be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.version = 0; 921be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.module = (struct hw_module_t *) module; 922be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.common.close = adev_close; 923be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 924be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_supported_devices = adev_get_supported_devices; 925be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.init_check = adev_init_check; 926be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_voice_volume = adev_set_voice_volume; 927be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_master_volume = adev_set_master_volume; 928be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_mode = adev_set_mode; 929be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_mic_mute = adev_set_mic_mute; 930be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_mic_mute = adev_get_mic_mute; 931be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.set_parameters = adev_set_parameters; 932be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_parameters = adev_get_parameters; 933be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.get_input_buffer_size = adev_get_input_buffer_size; 934be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.open_output_stream = adev_open_output_stream; 935be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.close_output_stream = adev_close_output_stream; 936be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.open_input_stream = adev_open_input_stream; 937be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.close_input_stream = adev_close_input_stream; 938be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin adev->device.dump = adev_dump; 939be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 940be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *device = &adev->device.common; 941be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 942be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return 0; 943be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 944be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_str_parms_create: 945be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin free(adev); 946be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin return ret; 947be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin} 948be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 949be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic struct hw_module_methods_t hal_module_methods = { 950be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .open = adev_open, 951be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 952be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 953be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct audio_module HAL_MODULE_INFO_SYM = { 954be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .common = { 955be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .tag = HARDWARE_MODULE_TAG, 956be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .version_major = 1, 957be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .version_minor = 0, 958be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .id = AUDIO_HARDWARE_MODULE_ID, 959be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .name = "A2DP Audio HW HAL", 960be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .author = "The Android Open Source Project", 961be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin .methods = &hal_module_methods, 962be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin }, 963be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}; 964be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 965be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin 966