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