blob: e455186ecf07889f096ceeb46b7508ce8783acc0 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2**
3** Copyright 2007, The Android Open Source Project
4**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08005** 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
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07008**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070010**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080011** 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
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070015** 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
34namespace android {
35
36// ----------------------------------------------------------------------------
37
38static char const * const kAudioDeviceName = "/dev/eac";
39
40// ----------------------------------------------------------------------------
41
42AudioHardwareGeneric::AudioHardwareGeneric()
43 : mOutput(0), mInput(0), mFd(-1), mMicMute(false)
44{
45 mFd = ::open(kAudioDeviceName, O_RDWR);
46}
47
48AudioHardwareGeneric::~AudioHardwareGeneric()
49{
50 if (mFd >= 0) ::close(mFd);
51 delete mOutput;
52 delete mInput;
53}
54
55status_t AudioHardwareGeneric::initCheck()
56{
57 if (mFd >= 0) {
58 if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
59 return NO_ERROR;
60 }
61 return NO_INIT;
62}
63
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070064AudioStreamOut* AudioHardwareGeneric::openOutputStream(
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080065 int format, int channelCount, uint32_t sampleRate, status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070066{
67 AutoMutex lock(mLock);
68
69 // only one output stream allowed
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080070 if (mOutput) {
71 if (status) {
72 *status = INVALID_OPERATION;
73 }
74 return 0;
75 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070076
77 // create new output stream
78 AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080079 status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate);
80 if (status) {
81 *status = lStatus;
82 }
83 if (lStatus == NO_ERROR) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070084 mOutput = out;
85 } else {
86 delete out;
87 }
88 return mOutput;
89}
90
91void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) {
92 if (out == mOutput) mOutput = 0;
93}
94
95AudioStreamIn* AudioHardwareGeneric::openInputStream(
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080096 int format, int channelCount, uint32_t sampleRate, status_t *status)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070097{
98 AutoMutex lock(mLock);
99
100 // only one input stream allowed
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800101 if (mInput) {
102 if (status) {
103 *status = INVALID_OPERATION;
104 }
105 return 0;
106 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700107
108 // create new output stream
109 AudioStreamInGeneric* in = new AudioStreamInGeneric();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800110 status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate);
111 if (status) {
112 *status = lStatus;
113 }
114 if (lStatus == NO_ERROR) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700115 mInput = in;
116 } else {
117 delete in;
118 }
119 return mInput;
120}
121
122void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) {
123 if (in == mInput) mInput = 0;
124}
125
126status_t AudioHardwareGeneric::setVoiceVolume(float v)
127{
128 // Implement: set voice volume
129 return NO_ERROR;
130}
131
132status_t AudioHardwareGeneric::setMasterVolume(float v)
133{
134 // Implement: set master volume
135 // return error - software mixer will handle it
136 return INVALID_OPERATION;
137}
138
139status_t AudioHardwareGeneric::setMicMute(bool state)
140{
141 mMicMute = state;
142 return NO_ERROR;
143}
144
145status_t AudioHardwareGeneric::getMicMute(bool* state)
146{
147 *state = mMicMute;
148 return NO_ERROR;
149}
150
151status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
152{
153 const size_t SIZE = 256;
154 char buffer[SIZE];
155 String8 result;
156 result.append("AudioHardwareGeneric::dumpInternals\n");
157 snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
158 result.append(buffer);
159 ::write(fd, result.string(), result.size());
160 return NO_ERROR;
161}
162
163status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
164{
165 dumpInternals(fd, args);
166 if (mInput) {
167 mInput->dump(fd, args);
168 }
169 if (mOutput) {
170 mOutput->dump(fd, args);
171 }
172 return NO_ERROR;
173}
174
175// ----------------------------------------------------------------------------
176
177status_t AudioStreamOutGeneric::set(
178 AudioHardwareGeneric *hw,
179 int fd,
180 int format,
181 int channels,
182 uint32_t rate)
183{
184 // fix up defaults
185 if (format == 0) format = AudioSystem::PCM_16_BIT;
186 if (channels == 0) channels = channelCount();
187 if (rate == 0) rate = sampleRate();
188
189 // check values
190 if ((format != AudioSystem::PCM_16_BIT) ||
191 (channels != channelCount()) ||
192 (rate != sampleRate()))
193 return BAD_VALUE;
194
195 mAudioHardware = hw;
196 mFd = fd;
197 return NO_ERROR;
198}
199
200AudioStreamOutGeneric::~AudioStreamOutGeneric()
201{
202 if (mAudioHardware)
203 mAudioHardware->closeOutputStream(this);
204}
205
206ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
207{
208 Mutex::Autolock _l(mLock);
209 return ssize_t(::write(mFd, buffer, bytes));
210}
211
The Android Open Source Project27629322009-01-09 17:51:23 -0800212status_t AudioStreamOutGeneric::standby()
213{
214 // Implement: audio hardware to standby mode
215 return NO_ERROR;
216}
217
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700218status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
219{
220 const size_t SIZE = 256;
221 char buffer[SIZE];
222 String8 result;
223 snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
224 result.append(buffer);
225 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
226 result.append(buffer);
227 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
228 result.append(buffer);
229 snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
230 result.append(buffer);
231 snprintf(buffer, SIZE, "\tformat: %d\n", format());
232 result.append(buffer);
233 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
234 result.append(buffer);
235 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
236 result.append(buffer);
237 ::write(fd, result.string(), result.size());
238 return NO_ERROR;
239}
240
241// ----------------------------------------------------------------------------
242
243// record functions
244status_t AudioStreamInGeneric::set(
245 AudioHardwareGeneric *hw,
246 int fd,
247 int format,
248 int channels,
249 uint32_t rate)
250{
251 // FIXME: remove logging
252 LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate);
253 // check values
254 if ((format != AudioSystem::PCM_16_BIT) ||
255 (channels != channelCount()) ||
256 (rate != sampleRate())) {
257 LOGE("Error opening input channel");
258 return BAD_VALUE;
259 }
260
261 mAudioHardware = hw;
262 mFd = fd;
263 return NO_ERROR;
264}
265
266AudioStreamInGeneric::~AudioStreamInGeneric()
267{
268 // FIXME: remove logging
269 LOGD("AudioStreamInGeneric destructor");
270 if (mAudioHardware)
271 mAudioHardware->closeInputStream(this);
272}
273
274ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
275{
276 // FIXME: remove logging
277 LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd);
278 AutoMutex lock(mLock);
279 if (mFd < 0) {
280 LOGE("Attempt to read from unopened device");
281 return NO_INIT;
282 }
283 return ::read(mFd, buffer, bytes);
284}
285
286status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
287{
288 const size_t SIZE = 256;
289 char buffer[SIZE];
290 String8 result;
291 snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
292 result.append(buffer);
293 snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
294 result.append(buffer);
295 snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
296 result.append(buffer);
297 snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
298 result.append(buffer);
299 snprintf(buffer, SIZE, "\tformat: %d\n", format());
300 result.append(buffer);
301 snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
302 result.append(buffer);
303 snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
304 result.append(buffer);
305 ::write(fd, result.string(), result.size());
306 return NO_ERROR;
307}
308
309// ----------------------------------------------------------------------------
310
311}; // namespace android