blob: a2b00f8f4a98e93bfd6dfc7a83d0bdc4e6a84c22 [file] [log] [blame]
Dima Zavinf0121592011-04-19 16:33:12 -07001/*
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"
33#include <media/AudioRecord.h>
34
Dima Zavine81531e2011-04-19 16:53:42 -070035#include <hardware_legacy/AudioSystemLegacy.h>
36
37namespace android_audio_legacy {
Dima Zavinf0121592011-04-19 16:33:12 -070038
39// ----------------------------------------------------------------------------
40
41static char const * const kAudioDeviceName = "/dev/eac";
42
43// ----------------------------------------------------------------------------
44
45AudioHardwareGeneric::AudioHardwareGeneric()
46 : mOutput(0), mInput(0), mFd(-1), mMicMute(false)
47{
48 mFd = ::open(kAudioDeviceName, O_RDWR);
49}
50
51AudioHardwareGeneric::~AudioHardwareGeneric()
52{
53 if (mFd >= 0) ::close(mFd);
54 closeOutputStream((AudioStreamOut *)mOutput);
55 closeInputStream((AudioStreamIn *)mInput);
56}
57
58status_t AudioHardwareGeneric::initCheck()
59{
60 if (mFd >= 0) {
61 if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
62 return NO_ERROR;
63 }
64 return NO_INIT;
65}
66
67AudioStreamOut* AudioHardwareGeneric::openOutputStream(
68 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
69{
70 AutoMutex lock(mLock);
71
72 // only one output stream allowed
73 if (mOutput) {
74 if (status) {
75 *status = INVALID_OPERATION;
76 }
77 return 0;
78 }
79
80 // create new output stream
81 AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
82 status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
83 if (status) {
84 *status = lStatus;
85 }
86 if (lStatus == NO_ERROR) {
87 mOutput = out;
88 } else {
89 delete out;
90 }
91 return mOutput;
92}
93
94void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
95 if (mOutput && out == mOutput) {
96 delete mOutput;
97 mOutput = 0;
98 }
99}
100
101AudioStreamIn* AudioHardwareGeneric::openInputStream(
102 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
103 status_t *status, AudioSystem::audio_in_acoustics acoustics)
104{
105 // check for valid input source
106 if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
107 return 0;
108 }
109
110 AutoMutex lock(mLock);
111
112 // only one input stream allowed
113 if (mInput) {
114 if (status) {
115 *status = INVALID_OPERATION;
116 }
117 return 0;
118 }
119
120 // create new output stream
121 AudioStreamInGeneric* in = new AudioStreamInGeneric();
122 status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
123 if (status) {
124 *status = lStatus;
125 }
126 if (lStatus == NO_ERROR) {
127 mInput = in;
128 } else {
129 delete in;
130 }
131 return mInput;
132}
133
134void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
135 if (mInput && in == mInput) {
136 delete mInput;
137 mInput = 0;
138 }
139}
140
141status_t AudioHardwareGeneric::setVoiceVolume(float v)
142{
143 // Implement: set voice volume
144 return NO_ERROR;
145}
146
147status_t AudioHardwareGeneric::setMasterVolume(float v)
148{
149 // Implement: set master volume
150 // return error - software mixer will handle it
151 return INVALID_OPERATION;
152}
153
154status_t AudioHardwareGeneric::setMicMute(bool state)
155{
156 mMicMute = state;
157 return NO_ERROR;
158}
159
160status_t AudioHardwareGeneric::getMicMute(bool* state)
161{
162 *state = mMicMute;
163 return NO_ERROR;
164}
165
166status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
167{
168 const size_t SIZE = 256;
169 char buffer[SIZE];
170 String8 result;
171 result.append("AudioHardwareGeneric::dumpInternals\n");
172 snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
173 result.append(buffer);
174 ::write(fd, result.string(), result.size());
175 return NO_ERROR;
176}
177
178status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
179{
180 dumpInternals(fd, args);
181 if (mInput) {
182 mInput->dump(fd, args);
183 }
184 if (mOutput) {
185 mOutput->dump(fd, args);
186 }
187 return NO_ERROR;
188}
189
190// ----------------------------------------------------------------------------
191
192status_t AudioStreamOutGeneric::set(
193 AudioHardwareGeneric *hw,
194 int fd,
195 uint32_t devices,
196 int *pFormat,
197 uint32_t *pChannels,
198 uint32_t *pRate)
199{
200 int lFormat = pFormat ? *pFormat : 0;
201 uint32_t lChannels = pChannels ? *pChannels : 0;
202 uint32_t lRate = pRate ? *pRate : 0;
203
204 // fix up defaults
205 if (lFormat == 0) lFormat = format();
206 if (lChannels == 0) lChannels = channels();
207 if (lRate == 0) lRate = sampleRate();
208
209 // check values
210 if ((lFormat != format()) ||
211 (lChannels != channels()) ||
212 (lRate != sampleRate())) {
213 if (pFormat) *pFormat = format();
214 if (pChannels) *pChannels = channels();
215 if (pRate) *pRate = sampleRate();
216 return BAD_VALUE;
217 }
218
219 if (pFormat) *pFormat = lFormat;
220 if (pChannels) *pChannels = lChannels;
221 if (pRate) *pRate = lRate;
222
223 mAudioHardware = hw;
224 mFd = fd;
225 mDevice = devices;
226 return NO_ERROR;
227}
228
229AudioStreamOutGeneric::~AudioStreamOutGeneric()
230{
231}
232
233ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
234{
235 Mutex::Autolock _l(mLock);
236 return ssize_t(::write(mFd, buffer, bytes));
237}
238
239status_t AudioStreamOutGeneric::standby()
240{
241 // Implement: audio hardware to standby mode
242 return NO_ERROR;
243}
244
245status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
246{
247 const size_t SIZE = 256;
248 char buffer[SIZE];
249 String8 result;
250 snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
251 result.append(buffer);
252 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
253 result.append(buffer);
254 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
255 result.append(buffer);
256 snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
257 result.append(buffer);
258 snprintf(buffer, SIZE, "\tformat: %d\n", format());
259 result.append(buffer);
260 snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
261 result.append(buffer);
262 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
263 result.append(buffer);
264 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
265 result.append(buffer);
266 ::write(fd, result.string(), result.size());
267 return NO_ERROR;
268}
269
270status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
271{
272 AudioParameter param = AudioParameter(keyValuePairs);
273 String8 key = String8(AudioParameter::keyRouting);
274 status_t status = NO_ERROR;
275 int device;
Steve Block6a705182011-10-20 11:56:19 +0100276 ALOGV("setParameters() %s", keyValuePairs.string());
Dima Zavinf0121592011-04-19 16:33:12 -0700277
278 if (param.getInt(key, device) == NO_ERROR) {
279 mDevice = device;
280 param.remove(key);
281 }
282
283 if (param.size()) {
284 status = BAD_VALUE;
285 }
286 return status;
287}
288
289String8 AudioStreamOutGeneric::getParameters(const String8& keys)
290{
291 AudioParameter param = AudioParameter(keys);
292 String8 value;
293 String8 key = String8(AudioParameter::keyRouting);
294
295 if (param.get(key, value) == NO_ERROR) {
296 param.addInt(key, (int)mDevice);
297 }
298
Steve Block6a705182011-10-20 11:56:19 +0100299 ALOGV("getParameters() %s", param.toString().string());
Dima Zavinf0121592011-04-19 16:33:12 -0700300 return param.toString();
301}
302
303status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames)
304{
305 return INVALID_OPERATION;
306}
307
308// ----------------------------------------------------------------------------
309
310// record functions
311status_t AudioStreamInGeneric::set(
312 AudioHardwareGeneric *hw,
313 int fd,
314 uint32_t devices,
315 int *pFormat,
316 uint32_t *pChannels,
317 uint32_t *pRate,
318 AudioSystem::audio_in_acoustics acoustics)
319{
320 if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
Steve Block6a705182011-10-20 11:56:19 +0100321 ALOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
Dima Zavinf0121592011-04-19 16:33:12 -0700322 // check values
323 if ((*pFormat != format()) ||
324 (*pChannels != channels()) ||
325 (*pRate != sampleRate())) {
Steve Block5efbd422012-01-08 10:18:02 +0000326 ALOGE("Error opening input channel");
Dima Zavinf0121592011-04-19 16:33:12 -0700327 *pFormat = format();
328 *pChannels = channels();
329 *pRate = sampleRate();
330 return BAD_VALUE;
331 }
332
333 mAudioHardware = hw;
334 mFd = fd;
335 mDevice = devices;
336 return NO_ERROR;
337}
338
339AudioStreamInGeneric::~AudioStreamInGeneric()
340{
341}
342
343ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
344{
345 AutoMutex lock(mLock);
346 if (mFd < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000347 ALOGE("Attempt to read from unopened device");
Dima Zavinf0121592011-04-19 16:33:12 -0700348 return NO_INIT;
349 }
350 return ::read(mFd, buffer, bytes);
351}
352
353status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
354{
355 const size_t SIZE = 256;
356 char buffer[SIZE];
357 String8 result;
358 snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
359 result.append(buffer);
360 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
361 result.append(buffer);
362 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
363 result.append(buffer);
364 snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
365 result.append(buffer);
366 snprintf(buffer, SIZE, "\tformat: %d\n", format());
367 result.append(buffer);
368 snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
369 result.append(buffer);
370 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
371 result.append(buffer);
372 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
373 result.append(buffer);
374 ::write(fd, result.string(), result.size());
375 return NO_ERROR;
376}
377
378status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
379{
380 AudioParameter param = AudioParameter(keyValuePairs);
381 String8 key = String8(AudioParameter::keyRouting);
382 status_t status = NO_ERROR;
383 int device;
Steve Block6a705182011-10-20 11:56:19 +0100384 ALOGV("setParameters() %s", keyValuePairs.string());
Dima Zavinf0121592011-04-19 16:33:12 -0700385
386 if (param.getInt(key, device) == NO_ERROR) {
387 mDevice = device;
388 param.remove(key);
389 }
390
391 if (param.size()) {
392 status = BAD_VALUE;
393 }
394 return status;
395}
396
397String8 AudioStreamInGeneric::getParameters(const String8& keys)
398{
399 AudioParameter param = AudioParameter(keys);
400 String8 value;
401 String8 key = String8(AudioParameter::keyRouting);
402
403 if (param.get(key, value) == NO_ERROR) {
404 param.addInt(key, (int)mDevice);
405 }
406
Steve Block6a705182011-10-20 11:56:19 +0100407 ALOGV("getParameters() %s", param.toString().string());
Dima Zavinf0121592011-04-19 16:33:12 -0700408 return param.toString();
409}
410
411// ----------------------------------------------------------------------------
412
413}; // namespace android