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