AudioHardware.cpp revision 7510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24
1/*
2** Copyright 2008, Google Inc.
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8**     http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17#include <math.h>
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "AudioHardwareMSM72XX"
21#include <utils/Log.h>
22#include <utils/String8.h>
23
24#include <stdio.h>
25#include <unistd.h>
26#include <sys/ioctl.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <dlfcn.h>
30#include <fcntl.h>
31
32// hardware specific functions
33
34#include "AudioHardware.h"
35
36#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
37
38namespace android {
39static int audpre_index, tx_iir_index;
40static void * acoustic;
41const uint32_t AudioHardware::inputSamplingRates[] = {
42        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
43};
44// ----------------------------------------------------------------------------
45
46AudioHardware::AudioHardware() :
47    mInit(false), mMicMute(true), mBluetoothNrec(true), mBluetoothId(0),
48    mOutput(0), mInput(0), mSndEndpoints(NULL),
49    SND_DEVICE_CURRENT(-1),
50    SND_DEVICE_HANDSET(-1),
51    SND_DEVICE_SPEAKER(-1),
52    SND_DEVICE_BT(-1),
53    SND_DEVICE_BT_EC_OFF(-1),
54    SND_DEVICE_HEADSET(-1),
55    SND_DEVICE_HEADSET_AND_SPEAKER(-1)
56{
57
58    int (*snd_get_num)();
59    int (*snd_get_endpoint)(int, msm_snd_endpoint *);
60    int (*set_acoustic_parameters)();
61
62    struct msm_snd_endpoint *ept;
63
64    acoustic = ::dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
65    if (acoustic == NULL ) {
66        LOGE("Could not open libhtc_acoustic.so");
67        return;
68    }
69
70    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
71    if ((*set_acoustic_parameters) == 0 ) {
72        LOGE("Could not open set_acoustic_parameters()");
73        return;
74    }
75
76    int rc = set_acoustic_parameters();
77    if (rc < 0) {
78        LOGE("Could not set acoustic parameters to share memory: %d", rc);
79//        return;
80    }
81
82    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num_endpoints");
83    if ((*snd_get_num) == 0 ) {
84        LOGE("Could not open snd_get_num()");
85//        return;
86    }
87
88    mNumSndEndpoints = snd_get_num();
89    LOGD("mNumSndEndpoints = %d", mNumSndEndpoints);
90    mSndEndpoints = new msm_snd_endpoint[mNumSndEndpoints];
91    mInit = true;
92    LOGV("constructed %d SND endpoints)", mNumSndEndpoints);
93    ept = mSndEndpoints;
94    snd_get_endpoint = (int (*)(int, msm_snd_endpoint *))::dlsym(acoustic, "snd_get_endpoint");
95    if ((*snd_get_endpoint) == 0 ) {
96        LOGE("Could not open snd_get_endpoint()");
97        return;
98    }
99
100    for (int cnt = 0; cnt < mNumSndEndpoints; cnt++, ept++) {
101        ept->id = cnt;
102        snd_get_endpoint(cnt, ept);
103#define CHECK_FOR(desc) \
104        if (!strcmp(ept->name, #desc)) { \
105            SND_DEVICE_##desc = ept->id; \
106            LOGD("BT MATCH " #desc); \
107        } else
108        CHECK_FOR(CURRENT)
109        CHECK_FOR(HANDSET)
110        CHECK_FOR(SPEAKER)
111        CHECK_FOR(BT)
112        CHECK_FOR(BT_EC_OFF)
113        CHECK_FOR(HEADSET)
114        CHECK_FOR(HEADSET_AND_SPEAKER) {}
115#undef CHECK_FOR
116    }
117}
118
119AudioHardware::~AudioHardware()
120{
121    delete mInput;
122    delete mOutput;
123    delete [] mSndEndpoints;
124    ::dlclose(acoustic);
125    mInit = false;
126}
127
128status_t AudioHardware::initCheck()
129{
130    return mInit ? NO_ERROR : NO_INIT;
131}
132
133AudioStreamOut* AudioHardware::openOutputStream(
134        int format, int channelCount, uint32_t sampleRate, status_t *status)
135{
136    Mutex::Autolock lock(mLock);
137
138    // only one output stream allowed
139    if (mOutput) {
140        if (status) {
141            *status = INVALID_OPERATION;
142        }
143        return 0;
144    }
145
146    // create new output stream
147    AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
148    status_t lStatus = out->set(this, format, channelCount, sampleRate);
149    if (status) {
150        *status = lStatus;
151    }
152    if (lStatus == NO_ERROR) {
153        mOutput = out;
154    } else {
155        delete out;
156    }
157    return mOutput;
158}
159
160void AudioHardware::closeOutputStream(AudioStreamOutMSM72xx* out) {
161    Mutex::Autolock lock(mLock);
162    if (mOutput != out) {
163        LOGW("Attempt to close invalid output stream");
164    }
165    else {
166        mOutput = 0;
167    }
168}
169
170AudioStreamIn* AudioHardware::openInputStream(
171        int format, int channelCount, uint32_t sampleRate, status_t *status,
172        AudioSystem::audio_in_acoustics acoustic_flags)
173{
174    mLock.lock();
175    // input stream already open?
176    if (mInput) {
177        if (status) {
178            *status = INVALID_OPERATION;
179        }
180        mLock.unlock();
181        return 0;
182    }
183
184    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
185    status_t lStatus = in->set(this, format, channelCount, sampleRate, acoustic_flags);
186    if (status) {
187        *status = lStatus;
188    }
189    if (lStatus != NO_ERROR) {
190        mLock.unlock();
191        delete in;
192        return 0;
193    }
194
195    mInput = in;
196    mLock.unlock();
197
198    return mInput;
199}
200
201void AudioHardware::closeInputStream(AudioStreamInMSM72xx* in) {
202    Mutex::Autolock lock(mLock);
203    if (mInput != in) {
204        LOGW("Attempt to close invalid input stream");
205    }
206    else {
207        mInput = 0;
208    }
209}
210
211bool AudioHardware::checkOutputStandby()
212{
213    if (mOutput)
214        if (!mOutput->checkStandby())
215            return false;
216
217    return true;
218}
219
220status_t AudioHardware::setMicMute(bool state)
221{
222    Mutex::Autolock lock(mLock);
223    return setMicMute_nosync(state);
224}
225
226// always call with mutex held
227status_t AudioHardware::setMicMute_nosync(bool state)
228{
229    if (mMicMute != state) {
230        mMicMute = state;
231        return doAudioRouteOrMute(SND_DEVICE_CURRENT);
232    }
233    return NO_ERROR;
234}
235
236status_t AudioHardware::getMicMute(bool* state)
237{
238    *state = mMicMute;
239    return NO_ERROR;
240}
241
242status_t AudioHardware::setParameter(const char *key, const char *value)
243{
244    LOGV("%s key = %s value = %s\n", __FUNCTION__, key, value);
245
246    if (key == NULL || value == NULL) {
247        LOGE("%s called with null argument, ignoring (key = %s, value = %s",
248             __FUNCTION__, key, value);
249        return BAD_VALUE;
250    }
251
252    const char BT_NREC_KEY[] = "bt_headset_nrec";
253    const char BT_NAME_KEY[] = "bt_headset_name";
254    const char BT_NREC_VALUE_ON[] = "on";
255
256    if (!strncmp(key, BT_NREC_KEY, sizeof(BT_NREC_KEY))) {
257        if (!strncmp(value, BT_NREC_VALUE_ON, sizeof(BT_NREC_VALUE_ON))) {
258            mBluetoothNrec = true;
259        } else {
260            mBluetoothNrec = false;
261            LOGI("Turning noise reduction and echo cancellation off for BT "
262                 "headset");
263        }
264        doRouting();
265    } else if (!strncmp(key, BT_NAME_KEY, sizeof(BT_NAME_KEY))) {
266        mBluetoothId = 0;
267        for (int i = 0; i < mNumSndEndpoints; i++) {
268            if (!strcasecmp(value, mSndEndpoints[i].name)) {
269                mBluetoothId = mSndEndpoints[i].id;
270                LOGI("Using custom acoustic parameters for %s", value);
271                break;
272            }
273        }
274        if (mBluetoothId == 0) {
275            LOGI("Using default acoustic parameters "
276                 "(%s not in acoustic database)", value);
277            doRouting();
278        }
279    }
280
281    return NO_ERROR;
282}
283static unsigned calculate_audpre_table_index(unsigned index)
284{
285    switch (index) {
286        case 48000:    return SAMP_RATE_INDX_48000;
287        case 44100:    return SAMP_RATE_INDX_44100;
288        case 32000:    return SAMP_RATE_INDX_32000;
289        case 24000:    return SAMP_RATE_INDX_24000;
290        case 22050:    return SAMP_RATE_INDX_22050;
291        case 16000:    return SAMP_RATE_INDX_16000;
292        case 12000:    return SAMP_RATE_INDX_12000;
293        case 11025:    return SAMP_RATE_INDX_11025;
294        case 8000:    return SAMP_RATE_INDX_8000;
295        default:     return -1;
296    }
297}
298size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
299{
300    if (checkInputSampleRate(sampleRate) != NO_ERROR) {
301        LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
302        return 0;
303    }
304    if (format != AudioSystem::PCM_16_BIT) {
305        LOGW("getInputBufferSize bad format: %d", format);
306        return 0;
307    }
308    if (channelCount < 1 || channelCount > 2) {
309        LOGW("getInputBufferSize bad channel count: %d", channelCount);
310        return 0;
311    }
312
313    return 2048*channelCount;
314}
315
316static status_t set_volume_rpc(uint32_t device,
317                               uint32_t method,
318                               uint32_t volume)
319{
320    int fd;
321#if LOG_SND_RPC
322    LOGD("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume);
323#endif
324
325    if (device == -1UL) return NO_ERROR;
326
327    fd = open("/dev/msm_snd", O_RDWR);
328    if (fd < 0) {
329        LOGE("Can not open snd device");
330        return -EPERM;
331    }
332    /* rpc_snd_set_volume(
333     *     device,            # Any hardware device enum, including
334     *                        # SND_DEVICE_CURRENT
335     *     method,            # must be SND_METHOD_VOICE to do anything useful
336     *     volume,            # integer volume level, in range [0,5].
337     *                        # note that 0 is audible (not quite muted)
338     *  )
339     * rpc_snd_set_volume only works for in-call sound volume.
340     */
341     struct msm_snd_volume_config args;
342     args.device = device;
343     args.method = method;
344     args.volume = volume;
345
346     if (ioctl(fd, SND_SET_VOLUME, &args) < 0) {
347         LOGE("snd_set_volume error.");
348         close(fd);
349         return -EIO;
350     }
351     close(fd);
352     return NO_ERROR;
353}
354
355status_t AudioHardware::setVoiceVolume(float v)
356{
357    if (v < 0.0) {
358        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
359        v = 0.0;
360    } else if (v > 1.0) {
361        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
362        v = 1.0;
363    }
364
365    int vol = lrint(v * 5.0);
366    LOGD("setVoiceVolume(%f)\n", v);
367    LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol);
368
369    set_volume_rpc(SND_DEVICE_CURRENT, SND_METHOD_VOICE, vol);
370    return NO_ERROR;
371}
372
373status_t AudioHardware::setMasterVolume(float v)
374{
375    Mutex::Autolock lock(mLock);
376    int vol = ceil(v * 5.0);
377    LOGI("Set master volume to %d.\n", vol);
378    set_volume_rpc(SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol);
379    set_volume_rpc(SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol);
380    set_volume_rpc(SND_DEVICE_BT,      SND_METHOD_VOICE, vol);
381    set_volume_rpc(SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol);
382    // We return an error code here to let the audioflinger do in-software
383    // volume on top of the maximum volume that we set through the SND API.
384    // return error - software mixer will handle it
385    return -1;
386}
387
388static status_t do_route_audio_rpc(uint32_t device,
389                                   bool ear_mute, bool mic_mute)
390{
391    if (device == -1UL)
392        return NO_ERROR;
393
394    int fd;
395#if LOG_SND_RPC
396    LOGD("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute);
397#endif
398
399    fd = open("/dev/msm_snd", O_RDWR);
400    if (fd < 0) {
401        LOGE("Can not open snd device");
402        return -EPERM;
403    }
404    // RPC call to switch audio path
405    /* rpc_snd_set_device(
406     *     device,            # Hardware device enum to use
407     *     ear_mute,          # Set mute for outgoing voice audio
408     *                        # this should only be unmuted when in-call
409     *     mic_mute,          # Set mute for incoming voice audio
410     *                        # this should only be unmuted when in-call or
411     *                        # recording.
412     *  )
413     */
414    struct msm_snd_device_config args;
415    args.device = device;
416    args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
417    args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
418
419    if (ioctl(fd, SND_SET_DEVICE, &args) < 0) {
420        LOGE("snd_set_device error.");
421        close(fd);
422        return -EIO;
423    }
424
425    close(fd);
426    return NO_ERROR;
427}
428
429// always call with mutex held
430status_t AudioHardware::doAudioRouteOrMute(uint32_t device)
431{
432    if (device == (uint32_t)SND_DEVICE_BT) {
433        if (mBluetoothId) {
434            device = mBluetoothId;
435        } else if (!mBluetoothNrec) {
436            device = SND_DEVICE_BT_EC_OFF;
437        }
438    }
439    return do_route_audio_rpc(device,
440                              mMode != AudioSystem::MODE_IN_CALL, mMicMute);
441}
442
443static int count_bits(uint32_t vector)
444{
445    int bits;
446    for (bits = 0; vector; bits++) {
447        vector &= vector - 1;
448    }
449    return bits;
450}
451
452status_t AudioHardware::doRouting()
453{
454    Mutex::Autolock lock(mLock);
455    uint32_t routes = mRoutes[mMode];
456    if (count_bits(routes) > 1) {
457        if (routes !=
458            (AudioSystem::ROUTE_HEADSET | AudioSystem::ROUTE_SPEAKER)) {
459            LOGW("Hardware does not support requested route combination (%#X),"
460                 " picking closest possible route...", routes);
461        }
462    }
463    int (*msm72xx_enable_audpp)(int);
464    msm72xx_enable_audpp = (int (*)(int))::dlsym(acoustic, "msm72xx_enable_audpp");
465    status_t ret = NO_ERROR;
466    if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
467        LOGI("Routing audio to Bluetooth PCM\n");
468        ret = doAudioRouteOrMute(SND_DEVICE_BT);
469        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
470    } else if ((routes & AudioSystem::ROUTE_HEADSET) &&
471               (routes & AudioSystem::ROUTE_SPEAKER)) {
472        LOGI("Routing audio to Wired Headset and Speaker\n");
473        ret = doAudioRouteOrMute(SND_DEVICE_HEADSET_AND_SPEAKER);
474        msm72xx_enable_audpp(ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
475    } else if (routes & AudioSystem::ROUTE_HEADSET) {
476        LOGI("Routing audio to Wired Headset\n");
477        ret = doAudioRouteOrMute(SND_DEVICE_HEADSET);
478        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
479    } else if (routes & AudioSystem::ROUTE_SPEAKER) {
480        LOGI("Routing audio to Speakerphone\n");
481        ret = doAudioRouteOrMute(SND_DEVICE_SPEAKER);
482        msm72xx_enable_audpp(ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
483    } else {
484        LOGI("Routing audio to Handset\n");
485        ret = doAudioRouteOrMute(SND_DEVICE_HANDSET);
486        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
487    }
488
489    return ret;
490}
491
492status_t AudioHardware::checkMicMute()
493{
494    Mutex::Autolock lock(mLock);
495    if (mMode != AudioSystem::MODE_IN_CALL) {
496        setMicMute_nosync(true);
497    }
498
499    return NO_ERROR;
500}
501
502status_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
503{
504    const size_t SIZE = 256;
505    char buffer[SIZE];
506    String8 result;
507    result.append("AudioHardware::dumpInternals\n");
508    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
509    result.append(buffer);
510    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
511    result.append(buffer);
512    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
513    result.append(buffer);
514    snprintf(buffer, SIZE, "\tmBluetoothId: %d\n", mBluetoothId);
515    result.append(buffer);
516    ::write(fd, result.string(), result.size());
517    return NO_ERROR;
518}
519
520status_t AudioHardware::dump(int fd, const Vector<String16>& args)
521{
522    dumpInternals(fd, args);
523    if (mInput) {
524        mInput->dump(fd, args);
525    }
526    if (mOutput) {
527        mOutput->dump(fd, args);
528    }
529    return NO_ERROR;
530}
531
532status_t AudioHardware::checkInputSampleRate(uint32_t sampleRate)
533{
534    for (uint32_t i = 0; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++) {
535        if (sampleRate == inputSamplingRates[i]) {
536            return NO_ERROR;
537        }
538    }
539    return BAD_VALUE;
540}
541
542// ----------------------------------------------------------------------------
543
544AudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
545    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true)
546{
547}
548
549status_t AudioHardware::AudioStreamOutMSM72xx::set(
550        AudioHardware* hw, int format, int channels, uint32_t rate)
551{
552    // fix up defaults
553    if (format == 0) format = AudioSystem::PCM_16_BIT;
554    if (channels == 0) channels = channelCount();
555    if (rate == 0) rate = sampleRate();
556
557    // check values
558    if ((format != AudioSystem::PCM_16_BIT) ||
559            (channels != channelCount()) ||
560            (rate != sampleRate()))
561        return BAD_VALUE;
562
563    mHardware = hw;
564
565    return NO_ERROR;
566}
567
568AudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
569{
570    if (mFd > 0) close(mFd);
571    mHardware->closeOutputStream(this);
572}
573
574ssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
575{
576    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
577    status_t status = NO_INIT;
578    size_t count = bytes;
579    const uint8_t* p = static_cast<const uint8_t*>(buffer);
580
581    if (mStandby) {
582
583        // open driver
584        LOGV("open driver");
585        status = ::open("/dev/msm_pcm_out", O_RDWR);
586        if (status < 0) {
587            LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
588            goto Error;
589        }
590        mFd = status;
591
592        // configuration
593        LOGV("get config");
594        struct msm_audio_config config;
595        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
596        if (status < 0) {
597            LOGE("Cannot read config");
598            goto Error;
599        }
600
601        LOGV("set config");
602        config.channel_count = channelCount();
603        config.sample_rate = sampleRate();
604        config.buffer_size = bufferSize();
605        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
606        config.codec_type = CODEC_TYPE_PCM;
607        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
608        if (status < 0) {
609            LOGE("Cannot set config");
610            goto Error;
611        }
612
613        LOGV("buffer_size: %u", config.buffer_size);
614        LOGV("buffer_count: %u", config.buffer_count);
615        LOGV("channel_count: %u", config.channel_count);
616        LOGV("sample_rate: %u", config.sample_rate);
617
618        // fill 2 buffers before AUDIO_START
619        mStartCount = AUDIO_HW_NUM_OUT_BUF;
620        mStandby = false;
621    }
622
623    while (count) {
624        ssize_t written = ::write(mFd, p, count);
625        if (written >= 0) {
626            count -= written;
627            p += written;
628        } else {
629            if (errno != EAGAIN) return written;
630            mRetryCount++;
631            LOGW("EAGAIN - retry");
632        }
633    }
634
635    // start audio after we fill 2 buffers
636    if (mStartCount) {
637        if (--mStartCount == 0) {
638            ioctl(mFd, AUDIO_START, 0);
639        }
640    }
641    return bytes;
642
643Error:
644    if (mFd > 0) {
645        ::close(mFd);
646        mFd = -1;
647    }
648    // Simulate audio output timing in case of error
649    usleep(bytes * 1000000 / frameSize() / sampleRate());
650
651    return status;
652}
653
654status_t AudioHardware::AudioStreamOutMSM72xx::standby()
655{
656    status_t status = NO_ERROR;
657    if (!mStandby && mFd > 0) {
658        ::close(mFd);
659        mFd = -1;
660    }
661    mStandby = true;
662    return status;
663}
664
665status_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
666{
667    const size_t SIZE = 256;
668    char buffer[SIZE];
669    String8 result;
670    result.append("AudioStreamOutMSM72xx::dump\n");
671    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
672    result.append(buffer);
673    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
674    result.append(buffer);
675    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
676    result.append(buffer);
677    snprintf(buffer, SIZE, "\tformat: %d\n", format());
678    result.append(buffer);
679    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
680    result.append(buffer);
681    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
682    result.append(buffer);
683    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
684    result.append(buffer);
685    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
686    result.append(buffer);
687    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
688    result.append(buffer);
689    ::write(fd, result.string(), result.size());
690    return NO_ERROR;
691}
692
693bool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
694{
695    return mStandby;
696}
697
698// ----------------------------------------------------------------------------
699
700AudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
701    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
702    mFormat(AUDIO_HW_IN_FORMAT), mChannelCount(AUDIO_HW_IN_CHANNELS),
703    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE),
704    mAcoustics((AudioSystem::audio_in_acoustics)0)
705{
706}
707
708status_t AudioHardware::AudioStreamInMSM72xx::set(
709        AudioHardware* hw, int format, int channelCount, uint32_t sampleRate,
710        AudioSystem::audio_in_acoustics acoustic_flags)
711{
712    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", format, channelCount, sampleRate);
713    if (mFd >= 0) {
714        LOGE("Audio record already open");
715        return -EPERM;
716    }
717
718    // open audio input device
719    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
720    if (status < 0) {
721        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
722        goto Error;
723    }
724    mFd = status;
725
726    // configuration
727    LOGV("get config");
728    struct msm_audio_config config;
729    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
730    if (status < 0) {
731        LOGE("Cannot read config");
732        goto Error;
733    }
734
735    LOGV("set config");
736    config.channel_count = channelCount;
737    config.sample_rate = sampleRate;
738    config.buffer_size = bufferSize();
739    config.buffer_count = 2;
740    config.codec_type = CODEC_TYPE_PCM;
741    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
742    if (status < 0) {
743        LOGE("Cannot set config");
744        goto Error;
745    }
746
747    LOGV("confirm config");
748    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
749    if (status < 0) {
750        LOGE("Cannot read config");
751        goto Error;
752    }
753    LOGV("buffer_size: %u", config.buffer_size);
754    LOGV("buffer_count: %u", config.buffer_count);
755    LOGV("channel_count: %u", config.channel_count);
756    LOGV("sample_rate: %u", config.sample_rate);
757
758    mFormat = format;
759    mChannelCount = config.channel_count;
760    mSampleRate = config.sample_rate;
761    mBufferSize = config.buffer_size;
762
763    mHardware = hw;
764    mHardware->setMicMute_nosync(false);
765    mState = AUDIO_INPUT_OPENED;
766    audpre_index = calculate_audpre_table_index(sampleRate);
767    tx_iir_index = (audpre_index * 2) + (hw->checkOutputStandby() ? 0 : 1);
768    LOGD("audpre_index = %d, tx_iir_index = %d\n", audpre_index, tx_iir_index);
769
770    /**
771     * If audio-preprocessing failed, we should not block record.
772     */
773    int (*msm72xx_set_audpre_params)(int, int);
774    msm72xx_set_audpre_params = (int (*)(int, int))::dlsym(acoustic, "msm72xx_set_audpre_params");
775    status = msm72xx_set_audpre_params(audpre_index, tx_iir_index);
776    if (status < 0)
777        LOGE("Cannot set audpre parameters");
778
779    int (*msm72xx_enable_audpre)(int, int, int);
780    msm72xx_enable_audpre = (int (*)(int, int, int))::dlsym(acoustic, "msm72xx_enable_audpre");
781    mAcoustics = acoustic_flags;
782    status = msm72xx_enable_audpre((int)acoustic_flags, audpre_index, tx_iir_index);
783    if (status < 0)
784        LOGE("Cannot enable audpre");
785
786    return NO_ERROR;
787
788Error:
789    if (mFd > 0) {
790        ::close(mFd);
791        mFd = -1;
792    }
793    return status;
794}
795
796AudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
797{
798    LOGV("AudioStreamInMSM72xx destructor");
799    if (mHardware) {
800        standby();
801        mHardware->closeInputStream(this);
802    }
803}
804
805ssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
806{
807    LOGV("AudioStreamInMSM72xx::read(%p, %u)", buffer, bytes);
808    if (!mHardware) return -1;
809
810    size_t count = bytes;
811    uint8_t* p = static_cast<uint8_t*>(buffer);
812
813    if (mState < AUDIO_INPUT_OPENED) {
814        if (set(mHardware, mFormat, mChannelCount, mSampleRate, mAcoustics) != NO_ERROR) {
815            return -1;
816        }
817    }
818
819    if (mState < AUDIO_INPUT_STARTED) {
820        if (ioctl(mFd, AUDIO_START, 0)) {
821            LOGE("Error starting record");
822            return -1;
823        }
824        mState = AUDIO_INPUT_STARTED;
825    }
826
827    while (count) {
828        ssize_t bytesRead = ::read(mFd, buffer, count);
829        if (bytesRead >= 0) {
830            count -= bytesRead;
831            p += bytesRead;
832        } else {
833            if (errno != EAGAIN) return bytesRead;
834            mRetryCount++;
835            LOGW("EAGAIN - retrying");
836        }
837    }
838    return bytes;
839}
840
841status_t AudioHardware::AudioStreamInMSM72xx::standby()
842{
843    if (!mHardware) return -1;
844    if (mState > AUDIO_INPUT_CLOSED) {
845        if (mFd > 0) {
846            ::close(mFd);
847            mFd = -1;
848        }
849        mHardware->checkMicMute();
850        mState = AUDIO_INPUT_CLOSED;
851    }
852    return NO_ERROR;
853}
854
855status_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
856{
857    const size_t SIZE = 256;
858    char buffer[SIZE];
859    String8 result;
860    result.append("AudioStreamInMSM72xx::dump\n");
861    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
862    result.append(buffer);
863    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
864    result.append(buffer);
865    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
866    result.append(buffer);
867    snprintf(buffer, SIZE, "\tformat: %d\n", format());
868    result.append(buffer);
869    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
870    result.append(buffer);
871    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
872    result.append(buffer);
873    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
874    result.append(buffer);
875    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
876    result.append(buffer);
877    ::write(fd, result.string(), result.size());
878    return NO_ERROR;
879}
880
881// ----------------------------------------------------------------------------
882
883extern "C" AudioHardwareInterface* createAudioHardware(void) {
884    return new AudioHardware();
885}
886
887}; // namespace android
888