15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2009-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Filename:      audio_a2dp_hw.c
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Description:   Implements hal for bluedroid a2dp audio device
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *****************************************************************************/
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2749120dc867c7818511b5afec461dfc97d17eef58Marie Janssen#define LOG_TAG "bt_a2dp_hw"
2849120dc867c7818511b5afec461dfc97d17eef58Marie Janssen
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <errno.h>
30109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include <fcntl.h>
3140421cbeef5836f5ca9a7c323121f5396db467c3Mark Salyzyn#include <inttypes.h>
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <pthread.h>
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdint.h>
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/errno.h>
35109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include <sys/socket.h>
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/stat.h>
37109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include <sys/time.h>
38109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include <sys/un.h>
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <unistd.h>
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <hardware/audio.h>
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <hardware/hardware.h>
43109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include <system/audio.h>
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
45109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include "audio_a2dp_hw.h"
46109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include "bt_utils.h"
4798a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou#include "osi/include/hash_map.h"
4898a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou#include "osi/include/hash_map_utils.h"
4944802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h"
50574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov#include "osi/include/osi.h"
51109691281c0135fd4298debcdec37fdc5855261eMiao Chou#include "osi/include/socket_utils/sockets.h"
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Constants & Macros
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define CTRL_CHAN_RETRY_COUNT 3
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define USEC_PER_SEC 1000000L
59f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent#define SOCK_SEND_TIMEOUT_MS 2000  /* Timeout for sending */
60f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent#define SOCK_RECV_TIMEOUT_MS 5000  /* Timeout for receiving */
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
625952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung// set WRITE_POLL_MS to 0 for blocking sockets, nonzero for polled non-blocking sockets
635952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung#define WRITE_POLL_MS 20
645952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define CASE_RETURN_STR(const) case const: return #const;
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
67db554581079863974af8e1289646f5deea6fc044Marie Janssen#define FNLOG()             LOG_VERBOSE(LOG_TAG, "%s", __FUNCTION__);
68db554581079863974af8e1289646f5deea6fc044Marie Janssen#define DEBUG(fmt, ...)     LOG_VERBOSE(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
69db554581079863974af8e1289646f5deea6fc044Marie Janssen#define INFO(fmt, ...)      LOG_INFO(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
705952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung#define WARN(fmt, ...)      LOG_WARN(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
71db554581079863974af8e1289646f5deea6fc044Marie Janssen#define ERROR(fmt, ...)     LOG_ERROR(LOG_TAG, "%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Local type definitions
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef enum {
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_STARTING,
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_STARTED,
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_STOPPING,
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_STOPPED,
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    AUDIO_A2DP_STATE_STANDBY    /* allows write to autoresume */
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} a2dp_state_t;
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
883e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstruct a2dp_stream_in;
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct a2dp_stream_out;
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct a2dp_audio_device {
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct audio_hw_device device;
933e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in  *input;
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *output;
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct a2dp_config {
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint32_t                rate;
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint32_t                channel_flags;
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int                     format;
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1053e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstruct a2dp_stream_common {
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_mutex_t         lock;
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int                     ctrl_fd;
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int                     audio_fd;
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    size_t                  buffer_sz;
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_config      cfg;
1113e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_state_t            state;
1123e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood};
1133e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
1143e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstruct a2dp_stream_out {
1153e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct audio_stream_out stream;
1163e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_common common;
117e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    uint64_t frames_presented; // frames written, never reset
118e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    uint64_t frames_rendered;  // frames written, reset on standby
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct a2dp_stream_in {
1223e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct audio_stream_in  stream;
1233e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_common common;
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static variables
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static functions
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic size_t out_get_buffer_size(const struct audio_stream *stream);
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Externs
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Functions
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
14312265e39b511f28425236b0dc97c78e7d837304bPavlin Radoslavov/* Function used only in debug mode */
14412265e39b511f28425236b0dc97c78e7d837304bPavlin Radoslavovstatic const char* dump_a2dp_ctrl_event(char event) __attribute__ ((unused));
145f56308e42dc38699111b416fe68da300bf41dfbfEric Laurentstatic void a2dp_open_ctrl_path(struct a2dp_stream_common *common);
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   Miscellaneous helper functions
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const char* dump_a2dp_ctrl_event(char event)
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    switch(event)
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        CASE_RETURN_STR(A2DP_CTRL_CMD_NONE)
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY)
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        CASE_RETURN_STR(A2DP_CTRL_CMD_START)
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        default:
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return "UNKNOWN MSG ID";
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* logs timestamp with microsec precision
1665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project   pprev is optional in case a dedicated diff is required */
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void ts_log(char *tag, int val, struct timespec *pprev_opt)
1685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct timespec now;
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    static struct timespec prev = {0,0};
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    unsigned long long now_us;
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    unsigned long long diff_us;
1735cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(tag);
1745cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(val);
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    clock_gettime(CLOCK_MONOTONIC, &now);
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (pprev_opt)
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *pprev_opt = now;
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        prev = now;
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int calc_audiotime(struct a2dp_config cfg, int bytes)
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int chan_count = popcount(cfg.channel_flags);
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT,
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            "unsupported sample sz", cfg.format);
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
201ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent    return (int)(((int64_t)bytes * (1000000 / (chan_count * 2))) / cfg.rate);
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   bluedroid stack adaptation
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2103e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int skt_connect(char *path, size_t buffer_sz)
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int ret;
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int skt_fd;
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int len;
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2163e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("connect to %s (sz %zu)", path, buffer_sz);
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
220109691281c0135fd4298debcdec37fdc5855261eMiao Chou    if(osi_socket_local_client_connect(skt_fd, path,
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("failed to connect (%s)", strerror(errno));
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        close(skt_fd);
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2283e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    len = buffer_sz;
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ret < 0)
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("setsockopt failed (%s)", strerror(errno));
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
233b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood    ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
2348de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    if (ret < 0)
2358de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov        ERROR("setsockopt failed (%s)", strerror(errno));
236b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood
2378de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    /* Socket send/receive timeout value */
2388de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    struct timeval tv;
239f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    tv.tv_sec = SOCK_SEND_TIMEOUT_MS / 1000;
240f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    tv.tv_usec = (SOCK_SEND_TIMEOUT_MS % 1000) * 1000;
2418de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov
2428de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
2438de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    if (ret < 0)
2448de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov        ERROR("setsockopt failed (%s)", strerror(errno));
2458de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov
246f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    tv.tv_sec = SOCK_RECV_TIMEOUT_MS / 1000;
247f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    tv.tv_usec = (SOCK_RECV_TIMEOUT_MS % 1000) * 1000;
248f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent
2498de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov    ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
250b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood    if (ret < 0)
251b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood        ERROR("setsockopt failed (%s)", strerror(errno));
252b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    INFO("connected to stack fd = %d", skt_fd);
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return skt_fd;
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
258b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwoodstatic int skt_read(int fd, void *p, size_t len)
2593e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood{
260574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    ssize_t read;
2613e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
2623e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    FNLOG();
2633e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
2643e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    ts_log("skt_read recv", len, NULL);
2653e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
266574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    OSI_NO_INTR(read = recv(fd, p, len, MSG_NOSIGNAL));
267574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    if (read == -1)
2688de3f0c9b01f65467d5f1586eb816818bd438a5ePavlin Radoslavov        ERROR("read failed with errno=%d\n", errno);
2693e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
270574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    return (int)read;
2713e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood}
2723e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int skt_write(int fd, const void *p, size_t len)
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
275574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    ssize_t sent;
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ts_log("skt_write", len, NULL);
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2805952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    if (WRITE_POLL_MS == 0) {
2815952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        // do not poll, use blocking send
2825952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        OSI_NO_INTR(sent = send(fd, p, len, MSG_NOSIGNAL));
2835952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        if (sent == -1)
2845952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            ERROR("write failed with error(%s)", strerror(errno));
2855952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung
2865952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        return (int)sent;
2875952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    }
2885952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung
2895952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    // use non-blocking send, poll
2905952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    int ms_timeout = SOCK_SEND_TIMEOUT_MS;
2915952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    size_t count = 0;
2925952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    while (count < len) {
2935952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        OSI_NO_INTR(sent = send(fd, p, len - count, MSG_NOSIGNAL | MSG_DONTWAIT));
2945952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        if (sent == -1) {
2955952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            if (errno != EAGAIN && errno != EWOULDBLOCK) {
2965952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung                ERROR("write failed with error(%s)", strerror(errno));
2975952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung                return -1;
2985952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            }
2995952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            if (ms_timeout >= WRITE_POLL_MS) {
3005952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung                usleep(WRITE_POLL_MS * 1000);
3015952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung                ms_timeout -= WRITE_POLL_MS;
3025952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung                continue;
3035952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            }
3045952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            WARN("write timeout exceeded, sent %zu bytes", count);
3055952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung            return -1;
3065952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        }
3075952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        count += sent;
3085952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung        p = (const uint8_t *)p + sent;
3095952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    }
3105952e40bef1afb310cd3bba7e673163d7e32d62cAndy Hung    return (int)count;
3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int skt_disconnect(int fd)
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    INFO("fd %d", fd);
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (fd != AUDIO_SKT_DISCONNECTED)
3185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        shutdown(fd, SHUT_RDWR);
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        close(fd);
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  AUDIO CONTROL PATH
3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3333e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length)
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
335574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    ssize_t ret;
336f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    int i;
337574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov
338f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    for (i = 0;; i++) {
339f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        OSI_NO_INTR(ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
340f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if (ret > 0) {
341f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            break;
342f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
343f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if (ret == 0) {
344f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("ack failed: peer closed");
345f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            break;
346f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
347f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if (errno != EWOULDBLOCK && errno != EAGAIN) {
348f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("ack failed: error(%s)", strerror(errno));
349f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            break;
350f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
351f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if (i == (CTRL_CHAN_RETRY_COUNT - 1)) {
352f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("ack failed: max retry count");
353f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            break;
354f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
355f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        INFO("ack failed (%s), retrying", strerror(errno));
356f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    }
357f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    if (ret <= 0) {
358574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov        skt_disconnect(common->ctrl_fd);
359574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
3605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3613e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return ret;
3623e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood}
3633e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
3643e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int a2dp_command(struct a2dp_stream_common *common, char cmd)
3653e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood{
3663e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    char ack;
3673e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
3683e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
3693e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
370f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
371f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        INFO("recovering from previous error");
372f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        a2dp_open_ctrl_path(common);
373f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
374f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("failure to open ctrl path");
375f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            return -1;
376f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
377f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    }
378f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent
3793e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    /* send command */
380574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    ssize_t sent;
381574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
382574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    if (sent == -1)
3833e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
3843e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("cmd failed (%s)", strerror(errno));
3853e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        skt_disconnect(common->ctrl_fd);
3863e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
3873e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
3883e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
3893e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
3903e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    /* wait for ack byte */
391aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov    if (a2dp_ctrl_receive(common, &ack, 1) < 0) {
392aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov        ERROR("A2DP COMMAND %s: no ACK", dump_a2dp_ctrl_event(cmd));
3933e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
394aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov    }
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3989c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    if (ack == A2DP_CTRL_ACK_INCALL_FAILURE)
3999c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta        return ack;
400aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov    if (ack != A2DP_CTRL_ACK_SUCCESS) {
401aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov        ERROR("A2DP COMMAND %s error %d", dump_a2dp_ctrl_event(cmd), ack);
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
403aee67ece726e9b5d0e2e02562fe013ae85c46d63Pavlin Radoslavov    }
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4083e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int check_a2dp_ready(struct a2dp_stream_common *common)
4093e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood{
4103e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0)
4113e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
4123e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("check a2dp ready failed");
4133e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
4143e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
4153e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return 0;
4163e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood}
4173e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4183e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int a2dp_read_audio_config(struct a2dp_stream_common *common)
4193e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood{
4203e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    uint32_t sample_rate;
4213e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    uint8_t channel_count;
4223e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4233e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0)
4243e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
4253e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("check a2dp ready failed");
4263e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
4273e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
4283e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4293e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0)
4303e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
4313e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_ctrl_receive(common, &channel_count, 1) < 0)
4323e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
4333e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4343e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO);
4353e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
4363e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->cfg.rate = sample_rate;
4373e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4383e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("got config %d %d", common->cfg.format, common->cfg.rate);
4393e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4403e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return 0;
4413e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood}
4423e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4433e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic void a2dp_open_ctrl_path(struct a2dp_stream_common *common)
4443e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood{
4453e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    int i;
4463e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4473e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    /* retry logic to catch any timing variations on control channel */
4483e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
4493e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
4503e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        /* connect control channel if not already connected */
4513e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0)
4523e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        {
4533e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            /* success, now check if stack is ready */
4543e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            if (check_a2dp_ready(common) == 0)
4553e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood                break;
4563e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4573e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            ERROR("error : a2dp not ready, wait 250 ms and retry");
4583e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            usleep(250000);
4593e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            skt_disconnect(common->ctrl_fd);
4603e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood            common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
4613e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        }
4623e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4633e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        /* ctrl channel not ready, wait a bit */
4643e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        usleep(250000);
4653e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
4663e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood}
4673e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** AUDIO DATA PATH
4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4743e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic void a2dp_stream_common_init(struct a2dp_stream_common *common)
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_mutexattr_t lock_attr;
4775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_mutexattr_init(&lock_attr);
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
4823e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    pthread_mutex_init(&common->lock, &lock_attr);
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4843e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
4853e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->audio_fd = AUDIO_SKT_DISCONNECTED;
4863e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->state = AUDIO_A2DP_STATE_STOPPED;
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* manages max capacity of socket pipe */
4893e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4923e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int start_audio_datapath(struct a2dp_stream_common *common)
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4943e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("state %d", common->state);
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4969c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    int oldstate = common->state;
4973e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->state = AUDIO_A2DP_STATE_STARTING;
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4999c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
5009c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    if (a2dp_status < 0)
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
502f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        ERROR("Audiopath start failed (status %d)", a2dp_status);
503f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        goto error;
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5059c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE)
5069c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    {
507f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        ERROR("Audiopath start failed - in call, move to suspended");
508f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        goto error;
5099c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    }
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* connect socket if not yet connected */
5123e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5143e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
5153e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        if (common->audio_fd < 0)
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
517f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("Audiopath start failed - error opening data socket");
518f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            goto error;
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
521f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    common->state = AUDIO_A2DP_STATE_STARTED;
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
523f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent
524f56308e42dc38699111b416fe68da300bf41dfbfEric Laurenterror:
525f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    common->state = oldstate;
526f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    return -1;
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5293e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int stop_audio_datapath(struct a2dp_stream_common *common)
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5313e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    int oldstate = common->state;
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5333e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("state %d", common->state);
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* prevent any stray output writes from autostarting the stream
5365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project       while stopping audiopath */
5373e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->state = AUDIO_A2DP_STATE_STOPPING;
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5393e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0)
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("audiopath stop failed");
5423e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        common->state = oldstate;
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5463e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->state = AUDIO_A2DP_STATE_STOPPED;
5475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* disconnect audio path */
5493e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    skt_disconnect(common->audio_fd);
5503e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->audio_fd = AUDIO_SKT_DISCONNECTED;
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5553e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwoodstatic int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
5565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5573e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("state %d", common->state);
5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5593e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (common->state == AUDIO_A2DP_STATE_STOPPING)
5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5623e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0)
5635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
5645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (standby)
5663e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        common->state = AUDIO_A2DP_STATE_STANDBY;
5675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
5683e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        common->state = AUDIO_A2DP_STATE_SUSPENDED;
5695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* disconnect audio path */
5713e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    skt_disconnect(common->audio_fd);
5725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5733e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    common->audio_fd = AUDIO_SKT_DISCONNECTED;
5745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
5765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
5805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  audio output callbacks
5825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
5845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
5865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                         size_t bytes)
5875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
589f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung    int sent = -1;
5905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5913e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
5925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
59396162b608ce2ad6d86214d7efd2bcc120d1f079cAnubhav Gupta    pthread_mutex_lock(&out->common.lock);
594f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED ||
595f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            out->common.state == AUDIO_A2DP_STATE_STOPPING) {
596f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        DEBUG("stream suspended or closing");
597f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        goto finish;
5985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* only allow autostarting if we are in stopped or standby */
6013e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
6023e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        (out->common.state == AUDIO_A2DP_STATE_STANDBY))
6035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6043e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        if (start_audio_datapath(&out->common) < 0)
6055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
606f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung            goto finish;
6075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6093e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    else if (out->common.state != AUDIO_A2DP_STATE_STARTED)
6105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("stream not in stopped or standby");
612f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        goto finish;
6135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
61596162b608ce2ad6d86214d7efd2bcc120d1f079cAnubhav Gupta    pthread_mutex_unlock(&out->common.lock);
6163e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    sent = skt_write(out->common.audio_fd, buffer,  bytes);
617f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_lock(&out->common.lock);
6185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
619e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    if (sent == -1) {
6203e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        skt_disconnect(out->common.audio_fd);
6213e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        out->common.audio_fd = AUDIO_SKT_DISCONNECTED;
622f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if ((out->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
623f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent                (out->common.state != AUDIO_A2DP_STATE_STOPPING)) {
62496162b608ce2ad6d86214d7efd2bcc120d1f079cAnubhav Gupta            out->common.state = AUDIO_A2DP_STATE_STOPPED;
625f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        } else {
62696162b608ce2ad6d86214d7efd2bcc120d1f079cAnubhav Gupta            ERROR("write failed : stream suspended, avoid resetting state");
627f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
628f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        goto finish;
6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
631f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hungfinish: ;
632ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent    const size_t frames = bytes / audio_stream_out_frame_size(stream);
633ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent    out->frames_rendered += frames;
634ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent    out->frames_presented += frames;
635f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_unlock(&out->common.lock);
636ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent
637f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung    // If send didn't work out, sleep to emulate write delay.
638f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung    if (sent == -1) {
639f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        const int us_delay = calc_audiotime(out->common.cfg, bytes);
640f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        DEBUG("emulate a2dp write delay (%d us)", us_delay);
641f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung        usleep(us_delay);
642f4a37b255d1d6fa4cf7cefe2aeb1c3f4fdf33f3cAndy Hung    }
643ec647fa1db61806a334fc883fb98679768ac4d0bEric Laurent    return bytes;
6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t out_get_sample_rate(const struct audio_stream *stream)
6475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
6495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6503e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("rate %" PRIu32,out->common.cfg.rate);
6515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6523e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return out->common.cfg.rate;
6535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
6565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
6585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
65940421cbeef5836f5ca9a7c323121f5396db467c3Mark Salyzyn    DEBUG("out_set_sample_rate : %" PRIu32, rate);
6605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (rate != AUDIO_STREAM_DEFAULT_RATE)
6625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE);
6645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
6655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6673e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    out->common.cfg.rate = rate;
6685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
6705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic size_t out_get_buffer_size(const struct audio_stream *stream)
6735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
675e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    // period_size is the AudioFlinger mixer buffer size.
676e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    const size_t period_size = out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
677e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */;
6785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
679e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    DEBUG("socket buffer size: %zu  period size: %zu", out->common.buffer_sz, period_size);
680e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    if (period_size % mixer_unit_size != 0) {
681e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung        ERROR("period size %zu not a multiple of %zu", period_size, mixer_unit_size);
682e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    }
6835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
684e97d975cce213b8c6e4f69bc3fc75411a1743647Andy Hung    return period_size;
6855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t out_get_channels(const struct audio_stream *stream)
6885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
6905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6913e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags);
6925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6933e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return out->common.cfg.channel_flags;
6945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic audio_format_t out_get_format(const struct audio_stream *stream)
6975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
6993e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("format 0x%x", out->common.cfg.format);
7003e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return out->common.cfg.format;
7015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_set_format(struct audio_stream *stream, audio_format_t format)
7045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
705cab5fc179730ce6910989307680b275195876c4dArman Uguray    UNUSED(stream);
7065cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(format);
7075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    DEBUG("setting format not yet supported (0x%x)", format);
7085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
7095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_standby(struct audio_stream *stream)
7125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
7135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
7145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int retVal = 0;
7155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
7175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7183e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    pthread_mutex_lock(&out->common.lock);
7199c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    // Do nothing in SUSPENDED state.
7209c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
7219c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta        retVal = suspend_audio_datapath(&out->common, true);
722e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    out->frames_rendered = 0; // rendered is reset, presented is not
7239c5d0727dd4cd09e44c032506c28ab4120ad3b88Anubhav Gupta    pthread_mutex_unlock (&out->common.lock);
7245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return retVal;
7265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_dump(const struct audio_stream *stream, int fd)
7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
730cab5fc179730ce6910989307680b275195876c4dArman Uguray    UNUSED(stream);
7315cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(fd);
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
7375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
7385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
7395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7403e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("state %d", out->common.state);
7415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
74298a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_t *params = hash_map_utils_new_from_string_params(kvpairs);
74398a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    int status = 0;
744118242b7bcf4cbd1568bcb383d1d69198aa63314Miao Chou
74598a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    if (!params)
74698a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou      return status;
7475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
748118242b7bcf4cbd1568bcb383d1d69198aa63314Miao Chou    pthread_mutex_lock(&out->common.lock);
749118242b7bcf4cbd1568bcb383d1d69198aa63314Miao Chou
7505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* dump params */
75198a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_utils_dump_string_keys_string_values(params);
7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
75398a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    char *keyval = (char *)hash_map_get(params, "closing");
7545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
75598a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    if (keyval && strcmp(keyval, "true") == 0)
7565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
75798a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        DEBUG("stream closing, disallow any writes");
75898a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        out->common.state = AUDIO_A2DP_STATE_STOPPING;
7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
76198a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    keyval = (char *)hash_map_get(params, "A2dpSuspended");
7625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
76398a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    if (keyval && strcmp(keyval, "true") == 0)
7645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
76598a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        if (out->common.state == AUDIO_A2DP_STATE_STARTED)
76698a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou            status = suspend_audio_datapath(&out->common, false);
76798a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    }
76898a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    else
76998a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    {
77098a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        /* Do not start the streaming automatically. If the phone was streaming
77198a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou         * prior to being suspended, the next out_write shall trigger the
77298a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou         * AVDTP start procedure */
77398a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
77498a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou            out->common.state = AUDIO_A2DP_STATE_STANDBY;
77598a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou        /* Irrespective of the state, return 0 */
7765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7783e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    pthread_mutex_unlock(&out->common.lock);
77998a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_free(params);
7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7813efd2322e130b521dd403a03676109ca325d7d3cEric Laurent    return status;
7825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic char * out_get_parameters(const struct audio_stream *stream, const char *keys)
7855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
786cab5fc179730ce6910989307680b275195876c4dArman Uguray    UNUSED(stream);
7875cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(keys);
7885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
7895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* add populating param here */
7915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return strdup("");
7935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t out_get_latency(const struct audio_stream_out *stream)
7965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
7975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int latency_us;
7985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
8005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
8025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8033e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    latency_us = ((out->common.buffer_sz * 1000 ) /
804171c23f2c009c8dceb5ca69729dff7913e23d3e6Eric Laurent                    audio_stream_out_frame_size(&out->stream) /
8053e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood                    out->common.cfg.rate) * 1000;
8065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (latency_us / 1000) + 200;
8095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_set_volume(struct audio_stream_out *stream, float left,
8125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                          float right)
8135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
8145cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
8155cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(left);
8165cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(right);
8175cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
8185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
8195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* volume controlled in audioflinger mixer (digital) */
8215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
8235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
825e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurentstatic int out_get_presentation_position(const struct audio_stream_out *stream,
826e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent                                         uint64_t *frames, struct timespec *timestamp)
827e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent{
828e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
829e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent
830e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    FNLOG();
831e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    if (stream == NULL || frames == NULL || timestamp == NULL)
832e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        return -EINVAL;
8335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
834e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    int ret = -EWOULDBLOCK;
835e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    pthread_mutex_lock(&out->common.lock);
836e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
837e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    if (out->frames_presented >= latency_frames) {
838e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        *frames = out->frames_presented - latency_frames;
839e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        clock_gettime(CLOCK_MONOTONIC, timestamp); // could also be associated with out_write().
840e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        ret = 0;
841e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    }
842e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    pthread_mutex_unlock(&out->common.lock);
843e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    return ret;
844e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent}
8455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_get_render_position(const struct audio_stream_out *stream,
8475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                   uint32_t *dsp_frames)
8485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
849e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
8505cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
8515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
852e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    if (stream == NULL || dsp_frames == NULL)
853e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        return -EINVAL;
854e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent
855e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    pthread_mutex_lock(&out->common.lock);
856e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
857e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    if (out->frames_rendered >= latency_frames) {
858e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames);
859e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    } else {
860e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent        *dsp_frames = 0;
861e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    }
862e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    pthread_mutex_unlock(&out->common.lock);
863e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    return 0;
8645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
8675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
8685cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
8695cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(effect);
8705cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
8715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
8725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
8735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
8765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
8775cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
8785cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(effect);
8795cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
8805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
8815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
8825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*
8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * AUDIO INPUT STREAM
8865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */
8875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t in_get_sample_rate(const struct audio_stream *stream)
8895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
8903e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
8915cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
8925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
8933e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return in->common.cfg.rate;
8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
8975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
8983e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
8995cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9013e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
9023e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
9033e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return 0;
9043e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    else
9053e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
9065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic size_t in_get_buffer_size(const struct audio_stream *stream)
9095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9105cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9115cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 320;
9145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t in_get_channels(const struct audio_stream *stream)
9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9183e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
9195cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9213e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return in->common.cfg.channel_flags;
9225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic audio_format_t in_get_format(const struct audio_stream *stream)
9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9265cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9275cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return AUDIO_FORMAT_PCM_16_BIT;
9305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_set_format(struct audio_stream *stream, audio_format_t format)
9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9345cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9355cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(format);
9365cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9383e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (format == AUDIO_FORMAT_PCM_16_BIT)
9393e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return 0;
9403e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    else
9413e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        return -1;
9425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_standby(struct audio_stream *stream)
9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9465cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9475cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_dump(const struct audio_stream *stream, int fd)
9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9545cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9555cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(fd);
9565cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
9595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
9625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9635cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9645cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(kvpairs);
9655cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
9685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic char * in_get_parameters(const struct audio_stream *stream,
9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                const char *keys)
9725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9735cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9745cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(keys);
9755cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return strdup("");
9785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_set_gain(struct audio_stream_in *stream, float gain)
9815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9825cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
9835cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(gain);
9845cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
9865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
9875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic ssize_t in_read(struct audio_stream_in *stream, void* buffer,
9905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                       size_t bytes)
9915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9923e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
9933e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    int read;
994f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    int us_delay;
9955cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
9963e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
9973e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
998f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_lock(&in->common.lock);
999f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED ||
1000f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            in->common.state == AUDIO_A2DP_STATE_STOPPING)
10013e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
10023e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        DEBUG("stream suspended");
1003f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        goto error;
10043e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
10053e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
10063e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    /* only allow autostarting if we are in stopped or standby */
10073e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
10083e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        (in->common.state == AUDIO_A2DP_STATE_STANDBY))
10093e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
10103e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        if (start_audio_datapath(&in->common) < 0)
10113e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        {
1012f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            goto error;
10133e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        }
10143e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
10153e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    else if (in->common.state != AUDIO_A2DP_STATE_STARTED)
10163e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
10173e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("stream not in stopped or standby");
1018f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        goto error;
10193e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
10203e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
1021f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_unlock(&in->common.lock);
1022b1c8fccbca8573555d6db07a2e44685f335800aaMike Lockwood    read = skt_read(in->common.audio_fd, buffer, bytes);
1023f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_lock(&in->common.lock);
10243e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (read == -1)
10253e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
10263e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        skt_disconnect(in->common.audio_fd);
10273e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
1028f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        if ((in->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
1029f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent                (in->common.state != AUDIO_A2DP_STATE_STOPPING)) {
1030f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            in->common.state = AUDIO_A2DP_STATE_STOPPED;
1031f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        } else {
1032f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            ERROR("read failed : stream suspended, avoid resetting state");
1033f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        }
1034f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent        goto error;
10353e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    } else if (read == 0) {
10363e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        DEBUG("read time out - return zeros");
10373e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        memset(buffer, 0, bytes);
10383e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        read = bytes;
10393e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
1040f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_unlock(&in->common.lock);
10413e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
10423e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("read %d bytes out of %zu bytes", read, bytes);
10433e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    return read;
1044f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent
1045f56308e42dc38699111b416fe68da300bf41dfbfEric Laurenterror:
1046f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    pthread_mutex_unlock(&in->common.lock);
1047f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    memset(buffer, 0, bytes);
1048f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    us_delay = calc_audiotime(in->common.cfg, bytes);
1049f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    DEBUG("emulate a2dp read delay (%d us)", us_delay);
1050f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent
1051f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    usleep(us_delay);
1052f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    return bytes;
10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
10565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10575cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
10585cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
10615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10655cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
10665cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(effect);
10675cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
10685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
10735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10745cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(stream);
10755cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(effect);
10765cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
10775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
10785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_open_output_stream(struct audio_hw_device *dev,
10835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                   audio_io_handle_t handle,
10845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                   audio_devices_t devices,
10855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                   audio_output_flags_t flags,
10865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                   struct audio_config *config,
108770311ac9119c65e48c26ce899181e683a3220562Eric Laurent                                   struct audio_stream_out **stream_out,
10888c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge                                   const char *address)
10895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
10925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out;
10935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int ret = 0;
10948c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(address);
10955cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(handle);
10965cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(devices);
10975cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(flags);
10985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    INFO("opening output");
11005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out));
11025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!out)
11045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -ENOMEM;
11055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.get_sample_rate = out_get_sample_rate;
11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.set_sample_rate = out_set_sample_rate;
11085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.get_buffer_size = out_get_buffer_size;
11095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.get_channels = out_get_channels;
11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.get_format = out_get_format;
11115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.set_format = out_set_format;
11125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.standby = out_standby;
11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.dump = out_dump;
11145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.set_parameters = out_set_parameters;
11155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.get_parameters = out_get_parameters;
11165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.add_audio_effect = out_add_audio_effect;
11175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.common.remove_audio_effect = out_remove_audio_effect;
11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.get_latency = out_get_latency;
11195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.set_volume = out_set_volume;
11205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.write = out_write;
11215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    out->stream.get_render_position = out_get_render_position;
1122e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent    out->stream.get_presentation_position = out_get_presentation_position;
1123e1eb6c4d68b03eb725b7da6d8832a96e8627b78eEric Laurent
11245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* initialize a2dp specifics */
11263e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_stream_common_init(&out->common);
11273e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
11283e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
11293e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
11303e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
11315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project   /* set output config values */
11335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project   if (config)
11345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project   {
11355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      config->format = out_get_format((const struct audio_stream *)&out->stream);
11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream);
11375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream);
11385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project   }
11395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *stream_out = &out->stream;
11405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    a2dp_dev->output = out;
11415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11423e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_open_ctrl_path(&out->common);
11433e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
11445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
11455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("ctrl socket failed to connect (%s)", strerror(errno));
11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ret = -1;
11475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        goto err_open;
11485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    DEBUG("success");
11518795a9a1789c4b32b7a2b99c7c09b4fb4ba3775dAnubhav Gupta    /* Delay to ensure Headset is in proper state when START is initiated
11528795a9a1789c4b32b7a2b99c7c09b4fb4ba3775dAnubhav Gupta       from DUT immediately after the connection due to ongoing music playback. */
11538795a9a1789c4b32b7a2b99c7c09b4fb4ba3775dAnubhav Gupta    usleep(250000);
11545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
11555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecterr_open:
11575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    free(out);
11585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *stream_out = NULL;
1159e67bf20a9d9df7f8835881711439c4319fbf2d24Nitin Srivastava    a2dp_dev->output = NULL;
11605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ERROR("failed");
11615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return ret;
11625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void adev_close_output_stream(struct audio_hw_device *dev,
11655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                     struct audio_stream_out *stream)
11665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
11675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
11685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
11695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11703e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("closing output (state %d)", out->common.state);
11715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1172764babe943fc2e559923c7bf8514664187808dddNitin Srivastava    pthread_mutex_lock(&out->common.lock);
1173f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    if ((out->common.state == AUDIO_A2DP_STATE_STARTED) ||
1174f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent            (out->common.state == AUDIO_A2DP_STATE_STOPPING)) {
11753e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        stop_audio_datapath(&out->common);
1176f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    }
11775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11783e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    skt_disconnect(out->common.ctrl_fd);
1179f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    out->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
11805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    free(stream);
11815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    a2dp_dev->output = NULL;
1182764babe943fc2e559923c7bf8514664187808dddNitin Srivastava    pthread_mutex_unlock(&out->common.lock);
11835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    DEBUG("done");
11855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
11885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
11895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
11905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_out *out = a2dp_dev->output;
11915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int retval = 0;
11925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (out == NULL)
11945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return retval;
119571ac7a776357e676c31908900d807e9f4dc26236Eric Laurent
11963e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("state %d", out->common.state);
11975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
11995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return retval;
12015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic char * adev_get_parameters(const struct audio_hw_device *dev,
12045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  const char *keys)
12055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12065cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
121098a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_t *params = hash_map_utils_new_from_string_params(keys);
121198a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_utils_dump_string_keys_string_values(params);
121298a9641e77a247e5ba9a7f263066058d17e2b0a0Miao Chou    hash_map_free(params);
12135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return strdup("");
12155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_init_check(const struct audio_hw_device *dev)
12185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1219cab5fc179730ce6910989307680b275195876c4dArman Uguray    UNUSED(dev);
12205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
12235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
12265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12275cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12285cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(volume);
12295cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
12335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume)
12365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12375cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12385cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(volume);
12395cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
12435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_set_mode(struct audio_hw_device *dev, int mode)
12465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12475cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12485cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(mode);
12495cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
12535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
12565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12575cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12585cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(state);
12595cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
12635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
12665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12675cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12685cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(state);
12695cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return -ENOSYS;
12735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
12765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                         const struct audio_config *config)
12775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12785cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(dev);
12795cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(config);
12805cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
12815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
12825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 320;
12845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_open_input_stream(struct audio_hw_device *dev,
12875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  audio_io_handle_t handle,
12885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  audio_devices_t devices,
12895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  struct audio_config *config,
129085f2cd2474077511105c1251a0a5a957c7f78669Glenn Kasten                                  struct audio_stream_in **stream_in,
12918c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge                                  audio_input_flags_t flags,
12928c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge                                  const char *address,
12938c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge                                  audio_source_t source)
12945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
12953e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
12965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_stream_in *in;
12975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int ret;
12988c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(address);
12995cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(config);
13008c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(devices);
13018c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(flags);
13028c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(handle);
13038c0d3947e3b65a4cc35c12729e43d8b1577306cdIan Coolidge    UNUSED(source);
13045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
13065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in));
13085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!in)
13105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -ENOMEM;
13115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.get_sample_rate = in_get_sample_rate;
13135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.set_sample_rate = in_set_sample_rate;
13145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.get_buffer_size = in_get_buffer_size;
13155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.get_channels = in_get_channels;
13165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.get_format = in_get_format;
13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.set_format = in_set_format;
13185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.standby = in_standby;
13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.dump = in_dump;
13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.set_parameters = in_set_parameters;
13215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.get_parameters = in_get_parameters;
13225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.add_audio_effect = in_add_audio_effect;
13235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.common.remove_audio_effect = in_remove_audio_effect;
13245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.set_gain = in_set_gain;
13255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.read = in_read;
13265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    in->stream.get_input_frames_lost = in_get_input_frames_lost;
13275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13283e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    /* initialize a2dp specifics */
13293e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_stream_common_init(&in->common);
13303e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *stream_in = &in->stream;
13323e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_dev->input = in;
13333e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13343e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_open_ctrl_path(&in->common);
13353e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
13363e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    {
13373e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("ctrl socket failed to connect (%s)", strerror(errno));
13383e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ret = -1;
13393e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        goto err_open;
13403e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
13413e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13423e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if (a2dp_read_audio_config(&in->common) < 0) {
13433e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ERROR("a2dp_read_audio_config failed (%s)", strerror(errno));
13443e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        ret = -1;
13453e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        goto err_open;
13463e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    }
13473e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13483e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("success");
13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
13505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecterr_open:
13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    free(in);
13535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *stream_in = NULL;
13543e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_dev->input = NULL;
13553e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    ERROR("failed");
13565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return ret;
13575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void adev_close_input_stream(struct audio_hw_device *dev,
13603e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood                                   struct audio_stream_in *stream)
13615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
13623e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
13633e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream;
13643e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_state_t state = in->common.state;
13655cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
13663e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    INFO("closing input (state %d)", state);
13673e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13683e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING))
13693e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood        stop_audio_datapath(&in->common);
13705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13713e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    skt_disconnect(in->common.ctrl_fd);
1372f56308e42dc38699111b416fe68da300bf41dfbfEric Laurent    in->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
13733e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    free(stream);
13743e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    a2dp_dev->input = NULL;
13753e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood
13763e8a242fcbeebea2857fa964ca48624d8433333eMike Lockwood    DEBUG("done");
13775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_dump(const audio_hw_device_t *device, int fd)
13805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
13815cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(device);
13825cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen    UNUSED(fd);
13835cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen
13845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
13855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
13875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_close(hw_device_t *device)
13905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
13915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    free(device);
13945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
13955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int adev_open(const hw_module_t* module, const char* name,
13985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     hw_device_t** device)
13995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
14005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct a2dp_audio_device *adev;
14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    INFO(" adev_open in A2dp_hw module");
14035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FNLOG();
14045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
14065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
14075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
14085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -EINVAL;
14095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev = calloc(1, sizeof(struct a2dp_audio_device));
14125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!adev)
14145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -ENOMEM;
14155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.common.tag = HARDWARE_DEVICE_TAG;
14179a445034f27ed64b46ae7f2914e6c1804a98716dEric Laurent    adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
14185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.common.module = (struct hw_module_t *) module;
14195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.common.close = adev_close;
14205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.init_check = adev_init_check;
14225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.set_voice_volume = adev_set_voice_volume;
14235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.set_master_volume = adev_set_master_volume;
14245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.set_mode = adev_set_mode;
14255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.set_mic_mute = adev_set_mic_mute;
14265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.get_mic_mute = adev_get_mic_mute;
14275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.set_parameters = adev_set_parameters;
14285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.get_parameters = adev_get_parameters;
14295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.get_input_buffer_size = adev_get_input_buffer_size;
14305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.open_output_stream = adev_open_output_stream;
14315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.close_output_stream = adev_close_output_stream;
14325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.open_input_stream = adev_open_input_stream;
14335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.close_input_stream = adev_close_input_stream;
14345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->device.dump = adev_dump;
14355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    adev->output = NULL;
14375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *device = &adev->device.common;
14405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return 0;
14425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
14435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic struct hw_module_methods_t hal_module_methods = {
14455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    .open = adev_open,
14465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
14475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1448a3aed3bd53e326ca79d8d01479d8737cd85729c5Ajay Panicker__attribute__ ((visibility ("default")))
14495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct audio_module HAL_MODULE_INFO_SYM = {
14505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    .common = {
14515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .tag = HARDWARE_MODULE_TAG,
14525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .version_major = 1,
14535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .version_minor = 0,
14545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .id = AUDIO_HARDWARE_MODULE_ID,
14555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .name = "A2DP Audio HW HAL",
14565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .author = "The Android Open Source Project",
14575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        .methods = &hal_module_methods,
14585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    },
14595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
1460