• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2008, The Android Open-Source Project
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 "AudioHardware"
21 
22 #include <utils/Log.h>
23 #include <utils/String8.h>
24 //#include <hardware_legacy/power.h>
25 
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/ioctl.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <dlfcn.h>
32 #include <fcntl.h>
33 
34 #include "AudioHardware.h"
35 #include <media/AudioRecord.h>
36 
37 extern "C" {
38 #include "msm_audio.h"
39 }
40 
41 
42 namespace android {
43 // ----------------------------------------------------------------------------
44 
AudioHardware()45 AudioHardware::AudioHardware() :
46     mInit(false), mMicMute(true), mOutput(0)
47 {
48     mInit = true;
49 }
50 
~AudioHardware()51 AudioHardware::~AudioHardware()
52 {
53     closeOutputStream((AudioStreamOut*)mOutput);
54     mInit = false;
55 }
56 
initCheck()57 status_t AudioHardware::initCheck()
58 {
59     return mInit ? NO_ERROR : NO_INIT;
60 }
61 
openOutputStream(uint32_t devices,int * format,uint32_t * channels,uint32_t * sampleRate,status_t * status)62 AudioStreamOut* AudioHardware::openOutputStream(
63         uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
64 {
65     { // scope for the lock
66         Mutex::Autolock lock(mLock);
67 
68         // only one output stream allowed
69         if (mOutput) {
70             if (status) {
71                 *status = INVALID_OPERATION;
72             }
73             return 0;
74         }
75 
76         AudioStreamOutQ5V2* out = new AudioStreamOutQ5V2();
77 
78         status_t rc = out->set(this, devices, format, channels, sampleRate);
79         if (rc) {
80             *status = rc;
81         }
82         if (rc == NO_ERROR) {
83             mOutput = out;
84         } else {
85             delete out;
86         }
87     }
88     return mOutput;
89 }
90 
closeOutputStream(AudioStreamOut * out)91 void AudioHardware::closeOutputStream(AudioStreamOut* out) {
92     Mutex::Autolock lock(mLock);
93     if (mOutput == 0 || mOutput != out) {
94         ALOGW("Attempt to close invalid output stream");
95     }
96     else {
97         delete mOutput;
98         mOutput = 0;
99     }
100 }
101 
openInputStream(uint32_t devices,int * format,uint32_t * channels,uint32_t * sampleRate,status_t * status,AudioSystem::audio_in_acoustics acoustic_flags)102 AudioStreamIn* AudioHardware::openInputStream(
103         uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
104         AudioSystem::audio_in_acoustics acoustic_flags)
105 {
106     return 0;
107 }
108 
closeInputStream(AudioStreamIn * in)109 void AudioHardware::closeInputStream(AudioStreamIn* in) {
110 }
111 
setMode(int mode)112 status_t AudioHardware::setMode(int mode)
113 {
114     return NO_ERROR;
115 }
116 
setMicMute(bool state)117 status_t AudioHardware::setMicMute(bool state)
118 {
119     return NO_ERROR;
120 }
121 
getMicMute(bool * state)122 status_t AudioHardware::getMicMute(bool* state)
123 {
124     *state = mMicMute;
125     return NO_ERROR;
126 }
127 
setParameters(const String8 & keyValuePairs)128 status_t AudioHardware::setParameters(const String8& keyValuePairs)
129 {
130     return NO_ERROR;
131 }
132 
getParameters(const String8 & keys)133 String8 AudioHardware::getParameters(const String8& keys)
134 {
135     AudioParameter request = AudioParameter(keys);
136     AudioParameter reply = AudioParameter();
137 
138     ALOGV("getParameters() %s", keys.string());
139 
140     return reply.toString();
141 }
142 
getInputBufferSize(uint32_t sampleRate,int format,int channelCount)143 size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
144 {
145     return 4096;
146 }
147 
setVoiceVolume(float v)148 status_t AudioHardware::setVoiceVolume(float v)
149 {
150     return NO_ERROR;
151 }
152 
setMasterVolume(float v)153 status_t AudioHardware::setMasterVolume(float v)
154 {
155     ALOGI("Set master volume to %f.\n", v);
156     // We return an error code here to let the audioflinger do in-software
157     // volume on top of the maximum volume that we set through the SND API.
158     // return error - software mixer will handle it
159     return -1;
160 }
161 
dump(int fd,const Vector<String16> & args)162 status_t AudioHardware::dump(int fd, const Vector<String16>& args)
163 {
164     return NO_ERROR;
165 }
166 
AudioStreamOutQ5V2()167 AudioHardware::AudioStreamOutQ5V2::AudioStreamOutQ5V2() :
168     mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true),
169     mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS), mSampleRate(AUDIO_HW_OUT_SAMPLERATE),
170     mBufferSize(AUDIO_HW_OUT_BUFSZ)
171 {
172 }
173 
set(AudioHardware * hw,uint32_t devices,int * pFormat,uint32_t * pChannels,uint32_t * pRate)174 status_t AudioHardware::AudioStreamOutQ5V2::set(
175         AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
176 {
177     int lFormat = pFormat ? *pFormat : 0;
178     uint32_t lChannels = pChannels ? *pChannels : 0;
179     uint32_t lRate = pRate ? *pRate : 0;
180 
181     mHardware = hw;
182     mDevices = devices;
183 
184     // fix up defaults
185     if (lFormat == 0) lFormat = format();
186     if (lChannels == 0) lChannels = channels();
187     if (lRate == 0) lRate = sampleRate();
188 
189     // check values
190     if ((lFormat != format()) ||
191         (lChannels != channels()) ||
192         (lRate != sampleRate())) {
193         if (pFormat) *pFormat = format();
194         if (pChannels) *pChannels = channels();
195         if (pRate) *pRate = sampleRate();
196         return BAD_VALUE;
197     }
198 
199     if (pFormat) *pFormat = lFormat;
200     if (pChannels) *pChannels = lChannels;
201     if (pRate) *pRate = lRate;
202 
203     mChannels = lChannels;
204     mSampleRate = lRate;
205     mBufferSize = 4096;
206 
207     return NO_ERROR;
208 }
209 
~AudioStreamOutQ5V2()210 AudioHardware::AudioStreamOutQ5V2::~AudioStreamOutQ5V2()
211 {
212     standby();
213 }
214 
write(const void * buffer,size_t bytes)215 ssize_t AudioHardware::AudioStreamOutQ5V2::write(const void* buffer, size_t bytes)
216 {
217     // ALOGD("AudioStreamOutQ5V2::write(%p, %u)", buffer, bytes);
218     status_t status = NO_INIT;
219     size_t count = bytes;
220     const uint8_t* p = static_cast<const uint8_t*>(buffer);
221 
222     if (mStandby) {
223         ALOGV("open pcm_out driver");
224         status = ::open("/dev/msm_pcm_out", O_RDWR);
225         if (status < 0) {
226                 ALOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
227             goto Error;
228         }
229         mFd = status;
230 
231         // configuration
232         ALOGV("get config");
233         struct msm_audio_config config;
234         status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
235         if (status < 0) {
236             ALOGE("Cannot read pcm_out config");
237             goto Error;
238         }
239 
240         ALOGV("set pcm_out config");
241         config.channel_count = AudioSystem::popCount(channels());
242         config.sample_rate = mSampleRate;
243         config.buffer_size = mBufferSize;
244         config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
245 //        config.codec_type = CODEC_TYPE_PCM;
246         status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
247         if (status < 0) {
248             ALOGE("Cannot set config");
249             goto Error;
250         }
251 
252         ALOGV("buffer_size: %u", config.buffer_size);
253         ALOGV("buffer_count: %u", config.buffer_count);
254         ALOGV("channel_count: %u", config.channel_count);
255         ALOGV("sample_rate: %u", config.sample_rate);
256 
257 #if 0
258         status = ioctl(mFd, AUDIO_START, &acdb_id);
259         if (status < 0) {
260             ALOGE("Cannot start pcm playback");
261             goto Error;
262         }
263 
264         status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
265         if (status < 0) {
266             ALOGE("Cannot start pcm playback");
267             goto Error;
268         }
269 #endif
270         mStandby = false;
271     }
272 
273     while (count) {
274         ssize_t written = ::write(mFd, p, count);
275         if (written >= 0) {
276             count -= written;
277             p += written;
278         } else {
279             if (errno != EAGAIN) return written;
280             mRetryCount++;
281             ALOGW("EAGAIN - retry");
282         }
283     }
284 
285     return bytes;
286 
287 Error:
288     if (mFd >= 0) {
289         ::close(mFd);
290         mFd = -1;
291     }
292     // Simulate audio output timing in case of error
293     usleep(bytes * 1000000 / frameSize() / sampleRate());
294 
295     return status;
296 }
297 
standby()298 status_t AudioHardware::AudioStreamOutQ5V2::standby()
299 {
300     status_t status = NO_ERROR;
301     if (!mStandby && mFd >= 0) {
302         ::close(mFd);
303         mFd = -1;
304     }
305     mStandby = true;
306     ALOGI("AudioHardware pcm playback is going to standby.");
307     return status;
308 }
309 
dump(int fd,const Vector<String16> & args)310 status_t AudioHardware::AudioStreamOutQ5V2::dump(int fd, const Vector<String16>& args)
311 {
312     return NO_ERROR;
313 }
314 
checkStandby()315 bool AudioHardware::AudioStreamOutQ5V2::checkStandby()
316 {
317     return mStandby;
318 }
319 
setParameters(const String8 & keyValuePairs)320 status_t AudioHardware::AudioStreamOutQ5V2::setParameters(const String8& keyValuePairs)
321 {
322     return NO_ERROR;
323 }
324 
getParameters(const String8 & keys)325 String8 AudioHardware::AudioStreamOutQ5V2::getParameters(const String8& keys)
326 {
327     AudioParameter param = AudioParameter(keys);
328     ALOGV("AudioStreamOutQ5V2::getParameters() %s", param.toString().string());
329     return param.toString();
330 }
331 
getRenderPosition(uint32_t * dspFrames)332 status_t AudioHardware::AudioStreamOutQ5V2::getRenderPosition(uint32_t *dspFrames)
333 {
334     return INVALID_OPERATION;
335 }
336 
createAudioHardware(void)337 extern "C" AudioHardwareInterface* createAudioHardware(void) {
338     return new AudioHardware();
339 }
340 
341 }; // namespace android
342