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