blob: 57874f3ce1aba4fcc6cf6d69602a52857a24e882 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdint.h>
19#include <sys/types.h>
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <unistd.h>
24#include <sched.h>
25#include <fcntl.h>
26#include <sys/ioctl.h>
27
28#define LOG_TAG "AudioHardware"
29#include <utils/Log.h>
30#include <utils/String8.h>
31
32#include "AudioHardwareGeneric.h"
Dave Sparksad216e52009-05-19 14:38:46 -070033#include <media/AudioRecord.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35namespace android {
36
37// ----------------------------------------------------------------------------
38
39static char const * const kAudioDeviceName = "/dev/eac";
40
41// ----------------------------------------------------------------------------
42
43AudioHardwareGeneric::AudioHardwareGeneric()
44 : mOutput(0), mInput(0), mFd(-1), mMicMute(false)
45{
46 mFd = ::open(kAudioDeviceName, O_RDWR);
47}
48
49AudioHardwareGeneric::~AudioHardwareGeneric()
50{
51 if (mFd >= 0) ::close(mFd);
Eric Laurenta553c252009-07-17 12:17:14 -070052 closeOutputStream((AudioStreamOut *)mOutput);
53 closeInputStream((AudioStreamIn *)mInput);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054}
55
56status_t AudioHardwareGeneric::initCheck()
57{
58 if (mFd >= 0) {
59 if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
60 return NO_ERROR;
61 }
62 return NO_INIT;
63}
64
65AudioStreamOut* AudioHardwareGeneric::openOutputStream(
Eric Laurenta553c252009-07-17 12:17:14 -070066 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067{
68 AutoMutex lock(mLock);
69
70 // only one output stream allowed
71 if (mOutput) {
72 if (status) {
73 *status = INVALID_OPERATION;
74 }
75 return 0;
76 }
77
78 // create new output stream
79 AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
Eric Laurenta553c252009-07-17 12:17:14 -070080 status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 if (status) {
82 *status = lStatus;
83 }
84 if (lStatus == NO_ERROR) {
85 mOutput = out;
86 } else {
87 delete out;
88 }
89 return mOutput;
90}
91
Eric Laurenta553c252009-07-17 12:17:14 -070092void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
93 if (mOutput && out == mOutput) {
94 delete mOutput;
95 mOutput = 0;
96 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097}
98
99AudioStreamIn* AudioHardwareGeneric::openInputStream(
Eric Laurenta553c252009-07-17 12:17:14 -0700100 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
Dave Sparksad216e52009-05-19 14:38:46 -0700101 status_t *status, AudioSystem::audio_in_acoustics acoustics)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102{
Dave Sparksad216e52009-05-19 14:38:46 -0700103 // check for valid input source
Eric Laurenta553c252009-07-17 12:17:14 -0700104 if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
Dave Sparksad216e52009-05-19 14:38:46 -0700105 return 0;
106 }
107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 AutoMutex lock(mLock);
109
110 // only one input stream allowed
111 if (mInput) {
112 if (status) {
113 *status = INVALID_OPERATION;
114 }
115 return 0;
116 }
117
118 // create new output stream
119 AudioStreamInGeneric* in = new AudioStreamInGeneric();
Eric Laurenta553c252009-07-17 12:17:14 -0700120 status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 if (status) {
122 *status = lStatus;
123 }
124 if (lStatus == NO_ERROR) {
125 mInput = in;
126 } else {
127 delete in;
128 }
129 return mInput;
130}
131
Eric Laurenta553c252009-07-17 12:17:14 -0700132void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
133 if (mInput && in == mInput) {
134 delete mInput;
135 mInput = 0;
136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137}
138
139status_t AudioHardwareGeneric::setVoiceVolume(float v)
140{
141 // Implement: set voice volume
142 return NO_ERROR;
143}
144
145status_t AudioHardwareGeneric::setMasterVolume(float v)
146{
147 // Implement: set master volume
148 // return error - software mixer will handle it
149 return INVALID_OPERATION;
150}
151
152status_t AudioHardwareGeneric::setMicMute(bool state)
153{
154 mMicMute = state;
155 return NO_ERROR;
156}
157
158status_t AudioHardwareGeneric::getMicMute(bool* state)
159{
160 *state = mMicMute;
161 return NO_ERROR;
162}
163
164status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
165{
166 const size_t SIZE = 256;
167 char buffer[SIZE];
168 String8 result;
169 result.append("AudioHardwareGeneric::dumpInternals\n");
170 snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
171 result.append(buffer);
172 ::write(fd, result.string(), result.size());
173 return NO_ERROR;
174}
175
176status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
177{
178 dumpInternals(fd, args);
179 if (mInput) {
180 mInput->dump(fd, args);
181 }
182 if (mOutput) {
183 mOutput->dump(fd, args);
184 }
185 return NO_ERROR;
186}
187
188// ----------------------------------------------------------------------------
189
190status_t AudioStreamOutGeneric::set(
191 AudioHardwareGeneric *hw,
192 int fd,
Eric Laurenta553c252009-07-17 12:17:14 -0700193 uint32_t devices,
194 int *pFormat,
195 uint32_t *pChannels,
196 uint32_t *pRate)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197{
Eric Laurenta553c252009-07-17 12:17:14 -0700198 int lFormat = pFormat ? *pFormat : 0;
199 uint32_t lChannels = pChannels ? *pChannels : 0;
200 uint32_t lRate = pRate ? *pRate : 0;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // fix up defaults
Eric Laurenta553c252009-07-17 12:17:14 -0700203 if (lFormat == 0) lFormat = format();
204 if (lChannels == 0) lChannels = channels();
205 if (lRate == 0) lRate = sampleRate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 // check values
Eric Laurenta553c252009-07-17 12:17:14 -0700208 if ((lFormat != format()) ||
209 (lChannels != channels()) ||
210 (lRate != sampleRate())) {
211 if (pFormat) *pFormat = format();
212 if (pChannels) *pChannels = channels();
213 if (pRate) *pRate = sampleRate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 return BAD_VALUE;
Eric Laurenta553c252009-07-17 12:17:14 -0700215 }
216
217 if (pFormat) *pFormat = lFormat;
218 if (pChannels) *pChannels = lChannels;
219 if (pRate) *pRate = lRate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
221 mAudioHardware = hw;
222 mFd = fd;
Eric Laurenta553c252009-07-17 12:17:14 -0700223 mDevice = devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 return NO_ERROR;
225}
226
227AudioStreamOutGeneric::~AudioStreamOutGeneric()
228{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229}
230
231ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
232{
233 Mutex::Autolock _l(mLock);
234 return ssize_t(::write(mFd, buffer, bytes));
235}
236
237status_t AudioStreamOutGeneric::standby()
238{
239 // Implement: audio hardware to standby mode
240 return NO_ERROR;
241}
242
243status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
244{
245 const size_t SIZE = 256;
246 char buffer[SIZE];
247 String8 result;
248 snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
249 result.append(buffer);
250 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
251 result.append(buffer);
252 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
253 result.append(buffer);
Eric Laurenta553c252009-07-17 12:17:14 -0700254 snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 result.append(buffer);
256 snprintf(buffer, SIZE, "\tformat: %d\n", format());
257 result.append(buffer);
Eric Laurenta553c252009-07-17 12:17:14 -0700258 snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
259 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
261 result.append(buffer);
262 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
263 result.append(buffer);
264 ::write(fd, result.string(), result.size());
265 return NO_ERROR;
266}
267
Eric Laurenta553c252009-07-17 12:17:14 -0700268status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
269{
270 AudioParameter param = AudioParameter(keyValuePairs);
271 String8 key = String8(AudioParameter::keyRouting);
272 status_t status = NO_ERROR;
273 int device;
274 LOGV("setParameters() %s", keyValuePairs.string());
275
276 if (param.getInt(key, device) == NO_ERROR) {
277 mDevice = device;
278 param.remove(key);
279 }
280
281 if (param.size()) {
282 status = BAD_VALUE;
283 }
284 return status;
285}
286
287String8 AudioStreamOutGeneric::getParameters(const String8& keys)
288{
289 AudioParameter param = AudioParameter(keys);
290 String8 value;
291 String8 key = String8(AudioParameter::keyRouting);
292
293 if (param.get(key, value) == NO_ERROR) {
294 param.addInt(key, (int)mDevice);
295 }
296
297 LOGV("getParameters() %s", param.toString().string());
298 return param.toString();
299}
300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301// ----------------------------------------------------------------------------
302
303// record functions
304status_t AudioStreamInGeneric::set(
305 AudioHardwareGeneric *hw,
306 int fd,
Eric Laurenta553c252009-07-17 12:17:14 -0700307 uint32_t devices,
308 int *pFormat,
309 uint32_t *pChannels,
310 uint32_t *pRate,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 AudioSystem::audio_in_acoustics acoustics)
312{
313 // FIXME: remove logging
Eric Laurenta553c252009-07-17 12:17:14 -0700314 if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
315 LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 // check values
Eric Laurenta553c252009-07-17 12:17:14 -0700317 if ((*pFormat != format()) ||
318 (*pChannels != channels()) ||
319 (*pRate != sampleRate())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 LOGE("Error opening input channel");
Eric Laurenta553c252009-07-17 12:17:14 -0700321 *pFormat = format();
322 *pChannels = channels();
323 *pRate = sampleRate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 return BAD_VALUE;
325 }
326
327 mAudioHardware = hw;
328 mFd = fd;
Eric Laurenta553c252009-07-17 12:17:14 -0700329 mDevice = devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 return NO_ERROR;
331}
332
333AudioStreamInGeneric::~AudioStreamInGeneric()
334{
335 // FIXME: remove logging
336 LOGD("AudioStreamInGeneric destructor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337}
338
339ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
340{
341 // FIXME: remove logging
Eric Laurenta553c252009-07-17 12:17:14 -0700342 LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, (int)bytes, mFd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 AutoMutex lock(mLock);
344 if (mFd < 0) {
345 LOGE("Attempt to read from unopened device");
346 return NO_INIT;
347 }
348 return ::read(mFd, buffer, bytes);
349}
350
351status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
352{
353 const size_t SIZE = 256;
354 char buffer[SIZE];
355 String8 result;
356 snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
357 result.append(buffer);
358 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
359 result.append(buffer);
360 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
361 result.append(buffer);
Eric Laurenta553c252009-07-17 12:17:14 -0700362 snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 result.append(buffer);
364 snprintf(buffer, SIZE, "\tformat: %d\n", format());
365 result.append(buffer);
Eric Laurenta553c252009-07-17 12:17:14 -0700366 snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
367 result.append(buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
369 result.append(buffer);
370 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
371 result.append(buffer);
372 ::write(fd, result.string(), result.size());
373 return NO_ERROR;
374}
375
Eric Laurenta553c252009-07-17 12:17:14 -0700376status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
377{
378 AudioParameter param = AudioParameter(keyValuePairs);
379 String8 key = String8(AudioParameter::keyRouting);
380 status_t status = NO_ERROR;
381 int device;
382 LOGV("setParameters() %s", keyValuePairs.string());
383
384 if (param.getInt(key, device) == NO_ERROR) {
385 mDevice = device;
386 param.remove(key);
387 }
388
389 if (param.size()) {
390 status = BAD_VALUE;
391 }
392 return status;
393}
394
395String8 AudioStreamInGeneric::getParameters(const String8& keys)
396{
397 AudioParameter param = AudioParameter(keys);
398 String8 value;
399 String8 key = String8(AudioParameter::keyRouting);
400
401 if (param.get(key, value) == NO_ERROR) {
402 param.addInt(key, (int)mDevice);
403 }
404
405 LOGV("getParameters() %s", param.toString().string());
406 return param.toString();
407}
408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409// ----------------------------------------------------------------------------
410
411}; // namespace android