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