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