blob: 8b9a5a75e5b79108513a3c6d83ec0966f3d41b7d [file] [log] [blame]
The Android Open Source Projectedbf3b62009-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 Sparksa5a11d42009-05-19 14:38:46 -070033#include <media/AudioRecord.h>
The Android Open Source Projectedbf3b62009-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);
52 delete mOutput;
53 delete mInput;
54}
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(
66 int format, int channelCount, uint32_t sampleRate, status_t *status)
67{
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();
80 status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate);
81 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
92void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) {
93 if (out == mOutput) mOutput = 0;
94}
95
96AudioStreamIn* AudioHardwareGeneric::openInputStream(
Dave Sparksa5a11d42009-05-19 14:38:46 -070097 int inputSource, int format, int channelCount, uint32_t sampleRate,
98 status_t *status, AudioSystem::audio_in_acoustics acoustics)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080099{
Dave Sparksa5a11d42009-05-19 14:38:46 -0700100 // check for valid input source
101 if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
102 (inputSource != AudioRecord::MIC_INPUT)) {
103 return 0;
104 }
105
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106 AutoMutex lock(mLock);
107
108 // only one input stream allowed
109 if (mInput) {
110 if (status) {
111 *status = INVALID_OPERATION;
112 }
113 return 0;
114 }
115
116 // create new output stream
117 AudioStreamInGeneric* in = new AudioStreamInGeneric();
118 status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics);
119 if (status) {
120 *status = lStatus;
121 }
122 if (lStatus == NO_ERROR) {
123 mInput = in;
124 } else {
125 delete in;
126 }
127 return mInput;
128}
129
Dave Sparksa5a11d42009-05-19 14:38:46 -0700130// DEPRECATED
131AudioStreamIn* AudioHardwareGeneric::openInputStream(
132 int format, int channelCount, uint32_t sampleRate, status_t *status,
133 AudioSystem::audio_in_acoustics acoustic_flags)
134{
135 return openInputStream(AudioRecord::DEFAULT_INPUT, format, channelCount,
136 sampleRate, status, acoustic_flags);
137}
138
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800139void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) {
140 if (in == mInput) mInput = 0;
141}
142
143status_t AudioHardwareGeneric::setVoiceVolume(float v)
144{
145 // Implement: set voice volume
146 return NO_ERROR;
147}
148
149status_t AudioHardwareGeneric::setMasterVolume(float v)
150{
151 // Implement: set master volume
152 // return error - software mixer will handle it
153 return INVALID_OPERATION;
154}
155
156status_t AudioHardwareGeneric::setMicMute(bool state)
157{
158 mMicMute = state;
159 return NO_ERROR;
160}
161
162status_t AudioHardwareGeneric::getMicMute(bool* state)
163{
164 *state = mMicMute;
165 return NO_ERROR;
166}
167
168status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
169{
170 const size_t SIZE = 256;
171 char buffer[SIZE];
172 String8 result;
173 result.append("AudioHardwareGeneric::dumpInternals\n");
174 snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
175 result.append(buffer);
176 ::write(fd, result.string(), result.size());
177 return NO_ERROR;
178}
179
180status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
181{
182 dumpInternals(fd, args);
183 if (mInput) {
184 mInput->dump(fd, args);
185 }
186 if (mOutput) {
187 mOutput->dump(fd, args);
188 }
189 return NO_ERROR;
190}
191
192// ----------------------------------------------------------------------------
193
194status_t AudioStreamOutGeneric::set(
195 AudioHardwareGeneric *hw,
196 int fd,
197 int format,
198 int channels,
199 uint32_t rate)
200{
201 // fix up defaults
202 if (format == 0) format = AudioSystem::PCM_16_BIT;
203 if (channels == 0) channels = channelCount();
204 if (rate == 0) rate = sampleRate();
205
206 // check values
207 if ((format != AudioSystem::PCM_16_BIT) ||
208 (channels != channelCount()) ||
209 (rate != sampleRate()))
210 return BAD_VALUE;
211
212 mAudioHardware = hw;
213 mFd = fd;
214 return NO_ERROR;
215}
216
217AudioStreamOutGeneric::~AudioStreamOutGeneric()
218{
219 if (mAudioHardware)
220 mAudioHardware->closeOutputStream(this);
221}
222
223ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
224{
225 Mutex::Autolock _l(mLock);
226 return ssize_t(::write(mFd, buffer, bytes));
227}
228
229status_t AudioStreamOutGeneric::standby()
230{
231 // Implement: audio hardware to standby mode
232 return NO_ERROR;
233}
234
235status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
236{
237 const size_t SIZE = 256;
238 char buffer[SIZE];
239 String8 result;
240 snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
241 result.append(buffer);
242 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
243 result.append(buffer);
244 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
245 result.append(buffer);
246 snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
247 result.append(buffer);
248 snprintf(buffer, SIZE, "\tformat: %d\n", format());
249 result.append(buffer);
250 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
251 result.append(buffer);
252 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
253 result.append(buffer);
254 ::write(fd, result.string(), result.size());
255 return NO_ERROR;
256}
257
258// ----------------------------------------------------------------------------
259
260// record functions
261status_t AudioStreamInGeneric::set(
262 AudioHardwareGeneric *hw,
263 int fd,
264 int format,
265 int channels,
266 uint32_t rate,
267 AudioSystem::audio_in_acoustics acoustics)
268{
269 // FIXME: remove logging
270 LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate);
271 // check values
272 if ((format != AudioSystem::PCM_16_BIT) ||
273 (channels != channelCount()) ||
274 (rate != sampleRate())) {
275 LOGE("Error opening input channel");
276 return BAD_VALUE;
277 }
278
279 mAudioHardware = hw;
280 mFd = fd;
281 return NO_ERROR;
282}
283
284AudioStreamInGeneric::~AudioStreamInGeneric()
285{
286 // FIXME: remove logging
287 LOGD("AudioStreamInGeneric destructor");
288 if (mAudioHardware)
289 mAudioHardware->closeInputStream(this);
290}
291
292ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
293{
294 // FIXME: remove logging
295 LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd);
296 AutoMutex lock(mLock);
297 if (mFd < 0) {
298 LOGE("Attempt to read from unopened device");
299 return NO_INIT;
300 }
301 return ::read(mFd, buffer, bytes);
302}
303
304status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
305{
306 const size_t SIZE = 256;
307 char buffer[SIZE];
308 String8 result;
309 snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
310 result.append(buffer);
311 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
312 result.append(buffer);
313 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
314 result.append(buffer);
315 snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
316 result.append(buffer);
317 snprintf(buffer, SIZE, "\tformat: %d\n", format());
318 result.append(buffer);
319 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
320 result.append(buffer);
321 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
322 result.append(buffer);
323 ::write(fd, result.string(), result.size());
324 return NO_ERROR;
325}
326
327// ----------------------------------------------------------------------------
328
329}; // namespace android