AudioHardware.cpp revision ba77ed6e3c6006d2797867f14ffd01e99cafc03b
1a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland/* 2a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** Copyright 2008, Google Inc. 3a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** 47510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 57510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** you may not use this file except in compliance with the License. 67510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** You may obtain a copy of the License at 7a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** 87510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 9a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** 107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** See the License for the specific language governing permissions and 14a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** limitations under the License. 15a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland*/ 16a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 17a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <math.h> 18a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//#define LOG_NDEBUG 0 20a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#define LOG_TAG "AudioHardwareMSM72XX" 21a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <utils/Log.h> 22a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <utils/String8.h> 23a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 24a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <stdio.h> 25a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <unistd.h> 26a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/ioctl.h> 27a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/types.h> 28a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/stat.h> 29a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <dlfcn.h> 30a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <fcntl.h> 31a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 32a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// hardware specific functions 33a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 34a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include "AudioHardware.h" 359e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks#include <media/AudioRecord.h> 36a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 37a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#define LOG_SND_RPC 0 // Set to 1 to log sound RPC's 38a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 39a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandnamespace android { 407510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic int audpre_index, tx_iir_index; 417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic void * acoustic; 427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectconst uint32_t AudioHardware::inputSamplingRates[] = { 437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 447510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}; 45a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ---------------------------------------------------------------------------- 46a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 47a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioHardware() : 487510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mInit(false), mMicMute(true), mBluetoothNrec(true), mBluetoothId(0), 492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mOutput(0), mSndEndpoints(NULL), mCurSndDevice(-1), 50a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland SND_DEVICE_CURRENT(-1), 51a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland SND_DEVICE_HANDSET(-1), 527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project SND_DEVICE_SPEAKER(-1), 53a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland SND_DEVICE_HEADSET(-1), 542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_BT(-1), 552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_CARKIT(-1), 562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_TTY_FULL(-1), 572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_TTY_VCO(-1), 582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_TTY_HCO(-1), 592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_NO_MIC_HEADSET(-1), 602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_FM_HEADSET(-1), 612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_HEADSET_AND_SPEAKER(-1), 622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_FM_SPEAKER(-1), 632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent SND_DEVICE_BT_EC_OFF(-1) 64a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 65a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*snd_get_num)(); 677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*snd_get_endpoint)(int, msm_snd_endpoint *); 687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*set_acoustic_parameters)(); 697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 707510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project struct msm_snd_endpoint *ept; 717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project acoustic = ::dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW); 737510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (acoustic == NULL ) { 747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Could not open libhtc_acoustic.so"); 75d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland /* this is not really an error on non-htc devices... */ 76d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland mNumSndEndpoints = 0; 7735f70b5d158659c59981365ecd8e2acfb09b3181Brian Swetland mInit = true; 787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return; 797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters"); 827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if ((*set_acoustic_parameters) == 0 ) { 837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Could not open set_acoustic_parameters()"); 843ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev return; 853ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev } 863ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev 877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int rc = set_acoustic_parameters(); 887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (rc < 0) { 897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Could not set acoustic parameters to share memory: %d", rc); 907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project// return; 917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num_endpoints"); 947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if ((*snd_get_num) == 0 ) { 957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Could not open snd_get_num()"); 967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project// return; 977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mNumSndEndpoints = snd_get_num(); 1007510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGD("mNumSndEndpoints = %d", mNumSndEndpoints); 1017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mSndEndpoints = new msm_snd_endpoint[mNumSndEndpoints]; 1027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mInit = true; 1037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGV("constructed %d SND endpoints)", mNumSndEndpoints); 1047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project ept = mSndEndpoints; 1057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project snd_get_endpoint = (int (*)(int, msm_snd_endpoint *))::dlsym(acoustic, "snd_get_endpoint"); 1067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if ((*snd_get_endpoint) == 0 ) { 1077510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Could not open snd_get_endpoint()"); 1087510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return; 1097510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 1107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 1117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project for (int cnt = 0; cnt < mNumSndEndpoints; cnt++, ept++) { 1127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project ept->id = cnt; 1137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project snd_get_endpoint(cnt, ept); 1147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project#define CHECK_FOR(desc) \ 1157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (!strcmp(ept->name, #desc)) { \ 1167510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project SND_DEVICE_##desc = ept->id; \ 1177510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGD("BT MATCH " #desc); \ 1187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } else 1197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(CURRENT) 1207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(HANDSET) 1217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(SPEAKER) 1227510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(BT) 1237510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(BT_EC_OFF) 1247510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(HEADSET) 1252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(CARKIT) 1262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(TTY_FULL) 1272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(TTY_VCO) 1282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(TTY_HCO) 1292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(NO_MIC_HEADSET) 1302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(FM_HEADSET) 1312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent CHECK_FOR(FM_SPEAKER) 1327510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project CHECK_FOR(HEADSET_AND_SPEAKER) {} 133a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#undef CHECK_FOR 134a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 135a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 136a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 137a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::~AudioHardware() 138a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 1392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent for (size_t index = 0; index < mInputs.size(); index++) { 1402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent closeInputStream((AudioStreamIn*)mInputs[index]); 1412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 1422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mInputs.clear(); 1432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent closeOutputStream((AudioStreamOut*)mOutput); 144a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland delete [] mSndEndpoints; 145d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland if (acoustic) { 146d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland ::dlclose(acoustic); 147d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland acoustic = 0; 148d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland } 149a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mInit = false; 150a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 151a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 152a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::initCheck() 153a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 154a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return mInit ? NO_ERROR : NO_INIT; 155a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 156a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 157a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream( 1582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status) 159a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 1602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent { // scope for the lock 1612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent Mutex::Autolock lock(mLock); 162a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent // only one output stream allowed 1642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (mOutput) { 1652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (status) { 1662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *status = INVALID_OPERATION; 1672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 1682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return 0; 1697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 170a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent // create new output stream 1722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx(); 1732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status_t lStatus = out->set(this, devices, format, channels, sampleRate); 1742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (status) { 1752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *status = lStatus; 1762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 1772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (lStatus == NO_ERROR) { 1782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mOutput = out; 1792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 1802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent delete out; 1812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 182a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 183a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return mOutput; 184a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 185a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentvoid AudioHardware::closeOutputStream(AudioStreamOut* out) { 187a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 1882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (mOutput == 0 || mOutput != out) { 189a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("Attempt to close invalid output stream"); 190a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 191a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland else { 1922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent delete mOutput; 193a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mOutput = 0; 194a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 195a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 196a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 197a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamIn* AudioHardware::openInputStream( 1982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status, 1992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioSystem::audio_in_acoustics acoustic_flags) 200a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 2019e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks // check for valid input source 2022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) { 2039e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks return 0; 2049e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks } 2059e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks 2067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mLock.lock(); 207a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 208a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx(); 2092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags); 2107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (status) { 2117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project *status = lStatus; 2127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 2137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (lStatus != NO_ERROR) { 2147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mLock.unlock(); 215a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland delete in; 216a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return 0; 217a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 218a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mInputs.add(in); 2207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mLock.unlock(); 2217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 2222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return in; 223a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 224a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentvoid AudioHardware::closeInputStream(AudioStreamIn* in) { 226a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 2272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 2282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in); 2292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (index < 0) { 230a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("Attempt to close invalid input stream"); 2312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 2322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mLock.unlock(); 2332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent delete mInputs[index]; 2342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mLock.lock(); 2352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mInputs.removeAt(index); 236a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 237a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 238a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2397510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::checkOutputStandby() 240a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 2417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mOutput) 2427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (!mOutput->checkStandby()) 2437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return false; 244a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2457510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return true; 246a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 247a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 248a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute(bool state) 249a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 250a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 251a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return setMicMute_nosync(state); 252a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 253a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 254a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held 255a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state) 256a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 257a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mMicMute != state) { 258a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mMicMute = state; 259a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return doAudioRouteOrMute(SND_DEVICE_CURRENT); 260a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 261a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 262a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 263a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 264a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state) 265a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 266a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland *state = mMicMute; 267a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 268a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 269a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::setParameters(const String8& keyValuePairs) 271a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 2722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioParameter param = AudioParameter(keyValuePairs); 2732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 value; 2742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 key; 275a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const char BT_NREC_KEY[] = "bt_headset_nrec"; 276a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const char BT_NAME_KEY[] = "bt_headset_name"; 277a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const char BT_NREC_VALUE_ON[] = "on"; 278a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 2792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 2802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("setParameters() %s", keyValuePairs.string()); 2812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 2822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (keyValuePairs.length() == 0) return BAD_VALUE; 2832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 2842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent key = String8(BT_NREC_KEY); 2852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.get(key, value) == NO_ERROR) { 2862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (value == BT_NREC_VALUE_ON) { 287a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mBluetoothNrec = true; 288a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } else { 289a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mBluetoothNrec = false; 290a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGI("Turning noise reduction and echo cancellation off for BT " 291a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland "headset"); 292a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 2932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 2942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent key = String8(BT_NAME_KEY); 2952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.get(key, value) == NO_ERROR) { 296a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mBluetoothId = 0; 2977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project for (int i = 0; i < mNumSndEndpoints; i++) { 2982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (!strcasecmp(value.string(), mSndEndpoints[i].name)) { 2997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mBluetoothId = mSndEndpoints[i].id; 3002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Using custom acoustic parameters for %s", value.string()); 301a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland break; 302a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 303a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 304a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mBluetoothId == 0) { 305a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGI("Using default acoustic parameters " 3062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent "(%s not in acoustic database)", value.string()); 3072735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent doRouting(NULL); 308a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 309a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 310a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 311a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 3122735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 3132735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::getParameters(const String8& keys) 3142735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{ 315ba77ed6e3c6006d2797867f14ffd01e99cafc03bEric Laurent AudioParameter param = AudioParameter(keys); 316ba77ed6e3c6006d2797867f14ffd01e99cafc03bEric Laurent return param.toString(); 3172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent} 3182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 3192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 3207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic unsigned calculate_audpre_table_index(unsigned index) 321a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 3227510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project switch (index) { 3237510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 48000: return SAMP_RATE_INDX_48000; 3247510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 44100: return SAMP_RATE_INDX_44100; 3257510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 32000: return SAMP_RATE_INDX_32000; 3267510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 24000: return SAMP_RATE_INDX_24000; 3277510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 22050: return SAMP_RATE_INDX_22050; 3287510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 16000: return SAMP_RATE_INDX_16000; 3297510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 12000: return SAMP_RATE_INDX_12000; 3307510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 11025: return SAMP_RATE_INDX_11025; 3317510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project case 8000: return SAMP_RATE_INDX_8000; 3327510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project default: return -1; 333a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 334a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 3357510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) 336a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 3377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (format != AudioSystem::PCM_16_BIT) { 3387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGW("getInputBufferSize bad format: %d", format); 3397510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return 0; 340a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 3417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (channelCount < 1 || channelCount > 2) { 3427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGW("getInputBufferSize bad channel count: %d", channelCount); 3437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return 0; 344a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 345a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 3467510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return 2048*channelCount; 347a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 348a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 349a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t set_volume_rpc(uint32_t device, 350a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland uint32_t method, 351a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland uint32_t volume) 352a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 353a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland int fd; 354a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC 355a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGD("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume); 356a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif 357a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 358a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (device == -1UL) return NO_ERROR; 359a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 360a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland fd = open("/dev/msm_snd", O_RDWR); 361a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (fd < 0) { 362a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Can not open snd device"); 363a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -EPERM; 364a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 365a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland /* rpc_snd_set_volume( 366a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * device, # Any hardware device enum, including 367a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * # SND_DEVICE_CURRENT 368a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * method, # must be SND_METHOD_VOICE to do anything useful 369a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * volume, # integer volume level, in range [0,5]. 370a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * # note that 0 is audible (not quite muted) 371a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * ) 372a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * rpc_snd_set_volume only works for in-call sound volume. 373a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland */ 3747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project struct msm_snd_volume_config args; 3757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project args.device = device; 3767510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project args.method = method; 3777510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project args.volume = volume; 378a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 3797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (ioctl(fd, SND_SET_VOLUME, &args) < 0) { 3807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("snd_set_volume error."); 3817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project close(fd); 3827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return -EIO; 3837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 3847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project close(fd); 3857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return NO_ERROR; 386a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 387a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 388a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v) 389a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 390a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (v < 0.0) { 391a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v); 392a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland v = 0.0; 393a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } else if (v > 1.0) { 394a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v); 395a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland v = 1.0; 396a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 397a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 398a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland int vol = lrint(v * 5.0); 399a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGD("setVoiceVolume(%f)\n", v); 400a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol); 401a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 402d066973de83218a24c773e5de04d10ed2d730873Eric Laurent Mutex::Autolock lock(mLock); 403a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland set_volume_rpc(SND_DEVICE_CURRENT, SND_METHOD_VOICE, vol); 404a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 405a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 406a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 407a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v) 408a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 409a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 410a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland int vol = ceil(v * 5.0); 411a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGI("Set master volume to %d.\n", vol); 4122735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent /* 413a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland set_volume_rpc(SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol); 414a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland set_volume_rpc(SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol); 415a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland set_volume_rpc(SND_DEVICE_BT, SND_METHOD_VOICE, vol); 416a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland set_volume_rpc(SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol); 4172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent */ 418a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // We return an error code here to let the audioflinger do in-software 419a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // volume on top of the maximum volume that we set through the SND API. 420a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // return error - software mixer will handle it 421a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -1; 422a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 423a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 424a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t do_route_audio_rpc(uint32_t device, 425a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland bool ear_mute, bool mic_mute) 426a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 427a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (device == -1UL) 428a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 429a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 430a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland int fd; 431a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC 432a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGD("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute); 433a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif 434a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 435a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland fd = open("/dev/msm_snd", O_RDWR); 436a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (fd < 0) { 437a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Can not open snd device"); 438a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -EPERM; 439a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 440a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // RPC call to switch audio path 441a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland /* rpc_snd_set_device( 442a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * device, # Hardware device enum to use 443a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * ear_mute, # Set mute for outgoing voice audio 444a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * # this should only be unmuted when in-call 445a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * mic_mute, # Set mute for incoming voice audio 446a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * # this should only be unmuted when in-call or 447a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * # recording. 448a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland * ) 449a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland */ 4503ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev struct msm_snd_device_config args; 451a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland args.device = device; 452a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED; 453a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED; 454a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 455a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (ioctl(fd, SND_SET_DEVICE, &args) < 0) { 456a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("snd_set_device error."); 457a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland close(fd); 458a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -EIO; 459a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 460a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 461a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland close(fd); 462a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 463a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 464a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 465a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held 466a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device) 467a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 468a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (device == (uint32_t)SND_DEVICE_BT) { 469a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mBluetoothId) { 470a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland device = mBluetoothId; 471a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } else if (!mBluetoothNrec) { 472a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland device = SND_DEVICE_BT_EC_OFF; 473a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 474a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 4752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("doAudioRouteOrMute() device %x, mMode %d, mMicMute %d", device, mMode, mMicMute); 476a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return do_route_audio_rpc(device, 4777510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mMode != AudioSystem::MODE_IN_CALL, mMicMute); 478a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 479a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 4802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::doRouting(AudioStreamInMSM72xx *input) 481a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 482d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland /* currently this code doesn't work without the htc libacoustic */ 483d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland if (!acoustic) 484d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland return 0; 485d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland 486a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 4872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t outputDevices = mOutput->devices(); 4882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status_t ret = NO_ERROR; 4897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*msm72xx_enable_audpp)(int); 4907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project msm72xx_enable_audpp = (int (*)(int))::dlsym(acoustic, "msm72xx_enable_audpp"); 4912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent int audProcess = (ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE); 4922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent int sndDevice = -1; 4932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 4942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (input != NULL) { 4952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t inputDevice = input->devices(); 4962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("do input routing device %x\n", inputDevice); 4972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (inputDevice != 0) { 4982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) { 4992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Bluetooth PCM\n"); 5002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_BT; 5012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) { 5022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) && 5032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) { 5042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Wired Headset and Speaker\n"); 5052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER; 5062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5072735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5082735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Wired Headset\n"); 5092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET; 5102735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5112735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5122735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) { 5132735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Speakerphone\n"); 5142735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_SPEAKER; 5152735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5162735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Handset\n"); 5182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HANDSET; 5192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5212735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent // if inputDevice == 0, restore output routing 5232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 5252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (sndDevice == -1) { 5262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (outputDevices & (outputDevices - 1)) { 5272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) { 5282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGW("Hardware does not support requested route combination (%#X)," 5292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent " picking closest possible route...", outputDevices); 5302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 5332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (outputDevices & AudioSystem::DEVICE_OUT_TTY) { 5342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to TTY\n"); 5352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_TTY_FULL; 5362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) { 5372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Bluetooth PCM\n"); 5382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_BT; 5392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) && 5402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) { 5412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Wired Headset and Speaker\n"); 5422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER; 5432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_SPEAKER) { 5452735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to FM Speakerphone (%d,%x)\n", mMode, outputDevices); 5462735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_FM_SPEAKER; 5472735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_DISABLE); 5482735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_HEADPHONE) { 5492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) { 5502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to FM Headset and Speaker (%d,%x)\n", mMode, outputDevices); 5512735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER; 5522735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5532735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to FM Headset (%d,%x)\n", mMode, outputDevices); 5552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = doAudioRouteOrMute(SND_DEVICE_FM_HEADSET); 5562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) { 5582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) { 5592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices); 5602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER; 5612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices); 5642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_NO_MIC_HEADSET; 5652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) { 5672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Wired Headset\n"); 5682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HEADSET; 5692735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) { 5702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Speakerphone\n"); 5712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_SPEAKER; 5722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE); 5732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGI("Routing audio to Handset\n"); 5752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent sndDevice = SND_DEVICE_HANDSET; 5762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 5792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (sndDevice != -1 && sndDevice != mCurSndDevice) { 5802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent ret = doAudioRouteOrMute(sndDevice); 5812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if ((*msm72xx_enable_audpp) == 0 ) { 5822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGE("Could not open msm72xx_enable_audpp()"); 5832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 5842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent msm72xx_enable_audpp(audProcess); 5852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 5862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mCurSndDevice = sndDevice; 587a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 588a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 589a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return ret; 590a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 591a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 592a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::checkMicMute() 593a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 594a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland Mutex::Autolock lock(mLock); 595a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mMode != AudioSystem::MODE_IN_CALL) { 596a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland setMicMute_nosync(true); 597a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 5987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 599a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 600a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 601a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 602a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args) 603a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 604a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const size_t SIZE = 256; 605a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland char buffer[SIZE]; 606a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland String8 result; 607a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append("AudioHardware::dumpInternals\n"); 608a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false"); 609a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 610a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false"); 611a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 612a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false"); 613a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 614a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmBluetoothId: %d\n", mBluetoothId); 615a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 616a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::write(fd, result.string(), result.size()); 617a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 618a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 619a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 620a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args) 621a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 622a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland dumpInternals(fd, args); 6232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent for (size_t index = 0; index < mInputs.size(); index++) { 6242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mInputs[index]->dump(fd, args); 625a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 6262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 627a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mOutput) { 628a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mOutput->dump(fd, args); 629a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 630a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 631a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 632a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 6332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentuint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate) 6347510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{ 6352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t i; 6362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t prevDelta; 6372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t delta; 6382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 6392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) { 6402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent delta = abs(sampleRate - inputSamplingRates[i]); 6412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (delta > prevDelta) break; 6427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 6432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent // i is always > 0 here 6442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return inputSamplingRates[i-1]; 6457510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project} 6467510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 647a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ---------------------------------------------------------------------------- 648a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 649a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() : 6502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0) 651a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 652a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 653a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 654a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set( 6552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate) 656a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 6572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent int lFormat = pFormat ? *pFormat : 0; 6582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t lChannels = pChannels ? *pChannels : 0; 6592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t lRate = pRate ? *pRate : 0; 6602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 6612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mHardware = hw; 6622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 663a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // fix up defaults 6642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (lFormat == 0) lFormat = format(); 6652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (lChannels == 0) lChannels = channels(); 6662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (lRate == 0) lRate = sampleRate(); 667a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 668a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // check values 6692735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if ((lFormat != format()) || 6702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent (lChannels != channels()) || 6712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent (lRate != sampleRate())) { 6722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pFormat) *pFormat = format(); 6732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pChannels) *pChannels = channels(); 6742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pRate) *pRate = sampleRate(); 675a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return BAD_VALUE; 6762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 677a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 6782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pFormat) *pFormat = lFormat; 6792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pChannels) *pChannels = lChannels; 6802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pRate) *pRate = lRate; 6812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 6822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mDevices = devices; 683a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 684a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 685a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 686a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 687a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx() 688a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 6897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mFd > 0) close(mFd); 690a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 691a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 692a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes) 693a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 694a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes); 695a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status_t status = NO_INIT; 696a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland size_t count = bytes; 697a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const uint8_t* p = static_cast<const uint8_t*>(buffer); 698a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 6997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mStandby) { 700a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 701a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // open driver 702a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("open driver"); 703a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ::open("/dev/msm_pcm_out", O_RDWR); 704a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 7057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno); 706a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 707a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 708a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mFd = status; 709a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 710a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // configuration 711a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("get config"); 712a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland struct msm_audio_config config; 713a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ioctl(mFd, AUDIO_GET_CONFIG, &config); 714a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 715a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Cannot read config"); 716a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 717a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 718a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 719a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("set config"); 7202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent config.channel_count = AudioSystem::popCount(channels()); 721a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.sample_rate = sampleRate(); 722a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.buffer_size = bufferSize(); 7237510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project config.buffer_count = AUDIO_HW_NUM_OUT_BUF; 724a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.codec_type = CODEC_TYPE_PCM; 725a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ioctl(mFd, AUDIO_SET_CONFIG, &config); 726a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 727a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Cannot set config"); 728a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 729a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 730a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 731a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("buffer_size: %u", config.buffer_size); 732a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("buffer_count: %u", config.buffer_count); 733a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("channel_count: %u", config.channel_count); 734a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("sample_rate: %u", config.sample_rate); 735a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 736a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // fill 2 buffers before AUDIO_START 7377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mStartCount = AUDIO_HW_NUM_OUT_BUF; 7387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mStandby = false; 739a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 740a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 741a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland while (count) { 742a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ssize_t written = ::write(mFd, p, count); 743a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (written >= 0) { 744a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland count -= written; 745a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland p += written; 746a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } else { 747a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (errno != EAGAIN) return written; 748a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mRetryCount++; 749a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("EAGAIN - retry"); 750a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 751a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 752a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 753a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // start audio after we fill 2 buffers 754a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mStartCount) { 755a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (--mStartCount == 0) { 756a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ioctl(mFd, AUDIO_START, 0); 757a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 758a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 759a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return bytes; 760a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 761a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError: 762a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mFd > 0) { 763a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::close(mFd); 764a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mFd = -1; 765a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 766a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // Simulate audio output timing in case of error 7677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project usleep(bytes * 1000000 / frameSize() / sampleRate()); 768a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 769a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return status; 770a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 771a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 772a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby() 773a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 774a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status_t status = NO_ERROR; 7757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (!mStandby && mFd > 0) { 776a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::close(mFd); 777a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mFd = -1; 778a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 7797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mStandby = true; 780a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return status; 781a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 782a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 783a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args) 784a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 785a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const size_t SIZE = 256; 786a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland char buffer[SIZE]; 787a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland String8 result; 788a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append("AudioStreamOutMSM72xx::dump\n"); 789a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); 790a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 791a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); 792a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 7932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent snprintf(buffer, SIZE, "\tchannels: %d\n", channels()); 794a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 795a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tformat: %d\n", format()); 796a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 797a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware); 798a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 799a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmFd: %d\n", mFd); 800a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 801a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount); 802a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 803a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount); 804a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 8057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false"); 8067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project result.append(buffer); 807a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::write(fd, result.string(), result.size()); 808a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 809a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 810a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 8117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::AudioStreamOutMSM72xx::checkStandby() 8127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{ 8137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return mStandby; 8147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project} 8157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 8162735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs) 8182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{ 8192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioParameter param = AudioParameter(keyValuePairs); 8202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 key = String8(AudioParameter::keyRouting); 8212735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status_t status = NO_ERROR; 8222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent int device; 8232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string()); 8242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.getInt(key, device) == NO_ERROR) { 8262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mDevices = device; 8272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("set output routing %x", mDevices); 8282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status = mHardware->doRouting(NULL); 8292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent param.remove(key); 8302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.size()) { 8332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status = BAD_VALUE; 8342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return status; 8362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent} 8372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys) 8392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{ 8402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioParameter param = AudioParameter(keys); 8412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 value; 8422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 key = String8(AudioParameter::keyRouting); 8432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.get(key, value) == NO_ERROR) { 8452735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("get routing %x", mDevices); 8462735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent param.addInt(key, (int)mDevices); 8472735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8482735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string()); 8502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return param.toString(); 8512735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent} 8522735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8532735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 854a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ---------------------------------------------------------------------------- 855a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 856a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() : 8577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0), 8582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS), 8597510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE), 8602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0) 861a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 862a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 863a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 864a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set( 8652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate, 8667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project AudioSystem::audio_in_acoustics acoustic_flags) 867a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 8682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) { 8692735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pFormat = AUDIO_HW_IN_FORMAT; 8702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return BAD_VALUE; 8712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pRate == 0) { 8732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return BAD_VALUE; 8742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent uint32_t rate = hw->getInputSampleRate(*pRate); 8762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (rate != *pRate) { 8772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pRate = rate; 8782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return BAD_VALUE; 8792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO && 8822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pChannels != AudioSystem::CHANNEL_IN_STEREO)) { 8832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pChannels = AUDIO_HW_IN_CHANNELS; 8842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return BAD_VALUE; 8852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 8862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mHardware = hw; 8882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 8892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate); 890a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mFd >= 0) { 891a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Audio record already open"); 892a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -EPERM; 893a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 894a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 895a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // open audio input device 896a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status_t status = ::open("/dev/msm_pcm_in", O_RDWR); 897a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 8987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno); 899a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 900a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 901a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mFd = status; 902a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 903a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland // configuration 904a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("get config"); 905a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland struct msm_audio_config config; 906a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ioctl(mFd, AUDIO_GET_CONFIG, &config); 907a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 908a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Cannot read config"); 909a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 910a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 911a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 912a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("set config"); 9132735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent config.channel_count = AudioSystem::popCount(*pChannels); 9142735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent config.sample_rate = *pRate; 915a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.buffer_size = bufferSize(); 916a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.buffer_count = 2; 917a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland config.codec_type = CODEC_TYPE_PCM; 918a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ioctl(mFd, AUDIO_SET_CONFIG, &config); 919a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 920a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Cannot set config"); 9212735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) { 9222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (config.channel_count == 1) { 9232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pChannels = AudioSystem::CHANNEL_IN_MONO; 9242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 9252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pChannels = AudioSystem::CHANNEL_IN_STEREO; 9262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 9272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent *pRate = config.sample_rate; 9282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 929a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 930a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 931a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 932a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("confirm config"); 933a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland status = ioctl(mFd, AUDIO_GET_CONFIG, &config); 934a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (status < 0) { 935a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Cannot read config"); 936a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland goto Error; 937a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 938a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("buffer_size: %u", config.buffer_size); 939a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("buffer_count: %u", config.buffer_count); 940a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("channel_count: %u", config.channel_count); 941a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGV("sample_rate: %u", config.sample_rate); 942a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 9432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mDevices = devices; 9442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mFormat = AUDIO_HW_IN_FORMAT; 9452735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mChannels = *pChannels; 9467510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mSampleRate = config.sample_rate; 9477510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mBufferSize = config.buffer_size; 9487510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 9492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent //mHardware->setMicMute_nosync(false); 9507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mState = AUDIO_INPUT_OPENED; 951d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland 952d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland if (!acoustic) 953d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland return NO_ERROR; 954d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland 9552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent audpre_index = calculate_audpre_table_index(mSampleRate); 9567510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project tx_iir_index = (audpre_index * 2) + (hw->checkOutputStandby() ? 0 : 1); 9577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGD("audpre_index = %d, tx_iir_index = %d\n", audpre_index, tx_iir_index); 9587510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 9597510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project /** 9607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project * If audio-preprocessing failed, we should not block record. 9617510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project */ 9627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*msm72xx_set_audpre_params)(int, int); 9637510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project msm72xx_set_audpre_params = (int (*)(int, int))::dlsym(acoustic, "msm72xx_set_audpre_params"); 9647510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project status = msm72xx_set_audpre_params(audpre_index, tx_iir_index); 9657510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (status < 0) 9667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Cannot set audpre parameters"); 9677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 9687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project int (*msm72xx_enable_audpre)(int, int, int); 9697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project msm72xx_enable_audpre = (int (*)(int, int, int))::dlsym(acoustic, "msm72xx_enable_audpre"); 9707510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mAcoustics = acoustic_flags; 9717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project status = msm72xx_enable_audpre((int)acoustic_flags, audpre_index, tx_iir_index); 9727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (status < 0) 9737510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGE("Cannot enable audpre"); 9747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 975a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 976a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 977a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError: 978a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (mFd > 0) { 979a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::close(mFd); 980a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mFd = -1; 981a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 982a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return status; 983a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 984a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 985a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx() 986a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 9877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project LOGV("AudioStreamInMSM72xx destructor"); 9882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent standby(); 989a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 990a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 991a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes) 992a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 993d066973de83218a24c773e5de04d10ed2d730873Eric Laurent LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes); 9947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (!mHardware) return -1; 995a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 996a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland size_t count = bytes; 997a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland uint8_t* p = static_cast<uint8_t*>(buffer); 998a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 9997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mState < AUDIO_INPUT_OPENED) { 1000d066973de83218a24c773e5de04d10ed2d730873Eric Laurent Mutex::Autolock lock(mHardware->mLock); 10012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) { 10027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return -1; 10037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 10047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 10052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 10067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mState < AUDIO_INPUT_STARTED) { 1007a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (ioctl(mFd, AUDIO_START, 0)) { 1008a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGE("Error starting record"); 1009a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return -1; 1010a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 10117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mState = AUDIO_INPUT_STARTED; 1012a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 1013a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1014a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland while (count) { 1015a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ssize_t bytesRead = ::read(mFd, buffer, count); 1016a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (bytesRead >= 0) { 1017a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland count -= bytesRead; 1018a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland p += bytesRead; 1019a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } else { 1020a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland if (errno != EAGAIN) return bytesRead; 1021a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland mRetryCount++; 1022a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland LOGW("EAGAIN - retrying"); 1023a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 1024a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland } 1025a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return bytes; 1026a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 1027a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 10287510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatus_t AudioHardware::AudioStreamInMSM72xx::standby() 10297510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{ 10307510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (!mHardware) return -1; 10317510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mState > AUDIO_INPUT_CLOSED) { 10327510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project if (mFd > 0) { 10337510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project ::close(mFd); 10347510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mFd = -1; 10357510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 10362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent //mHardware->checkMicMute(); 10377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project mState = AUDIO_INPUT_CLOSED; 10387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project } 10397510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project return NO_ERROR; 10407510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project} 10417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project 1042a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args) 1043a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{ 1044a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland const size_t SIZE = 256; 1045a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland char buffer[SIZE]; 1046a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland String8 result; 1047a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append("AudioStreamInMSM72xx::dump\n"); 1048a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); 1049a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1050a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); 1051a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 10522735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent snprintf(buffer, SIZE, "\tchannels: %d\n", channels()); 1053a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1054a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tformat: %d\n", format()); 1055a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1056a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware); 1057a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1058a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd); 1059a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 10607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project snprintf(buffer, SIZE, "\tmState: %d\n", mState); 1061a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1062a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount); 1063a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland result.append(buffer); 1064a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland ::write(fd, result.string(), result.size()); 1065a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return NO_ERROR; 1066a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 1067a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 10682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs) 10692735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{ 10702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioParameter param = AudioParameter(keyValuePairs); 10712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 key = String8(AudioParameter::keyRouting); 10722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status_t status = NO_ERROR; 10732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent int device; 10742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string()); 10752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 10762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.getInt(key, device) == NO_ERROR) { 10772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("set input routing %x", device); 10782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (device & (device - 1)) { 10792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status = BAD_VALUE; 10802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } else { 10812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent mDevices = device; 10822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status = mHardware->doRouting(this); 10832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 10842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent param.remove(key); 10852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 10862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 10872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.size()) { 10882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent status = BAD_VALUE; 10892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 10902735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return status; 10912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent} 10922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 10932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys) 10942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{ 10952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent AudioParameter param = AudioParameter(keys); 10962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 value; 10972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent String8 key = String8(AudioParameter::keyRouting); 10982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 10992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent if (param.get(key, value) == NO_ERROR) { 11002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("get routing %x", mDevices); 11012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent param.addInt(key, (int)mDevices); 11022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent } 11032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 11042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string()); 11052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent return param.toString(); 11062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent} 11072735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent 1108a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ---------------------------------------------------------------------------- 1109a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1110a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) { 1111a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland return new AudioHardware(); 1112a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland} 1113a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland 1114a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}; // namespace android 1115