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