blob: e6a163b7c6d0525b82d0c6b8e1f2d9debf0d1e22 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2**
3** Copyright 2007, The Android Open Source Project
4**
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-10-21 07:00:00 -07008**
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070010**
The Android Open Source Projectf013e1a2008-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 Project54b6cfa2008-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
64status_t AudioHardwareGeneric::standby()
65{
66 // Implement: audio hardware to standby mode
67 return NO_ERROR;
68}
69
70AudioStreamOut* AudioHardwareGeneric::openOutputStream(
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080071 int format, int channelCount, uint32_t sampleRate, status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070072{
73 AutoMutex lock(mLock);
74
75 // only one output stream allowed
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080076 if (mOutput) {
77 if (status) {
78 *status = INVALID_OPERATION;
79 }
80 return 0;
81 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070082
83 // create new output stream
84 AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080085 status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate);
86 if (status) {
87 *status = lStatus;
88 }
89 if (lStatus == NO_ERROR) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070090 mOutput = out;
91 } else {
92 delete out;
93 }
94 return mOutput;
95}
96
97void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) {
98 if (out == mOutput) mOutput = 0;
99}
100
101AudioStreamIn* AudioHardwareGeneric::openInputStream(
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800102 int format, int channelCount, uint32_t sampleRate, status_t *status)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700103{
104 AutoMutex lock(mLock);
105
106 // only one input stream allowed
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800107 if (mInput) {
108 if (status) {
109 *status = INVALID_OPERATION;
110 }
111 return 0;
112 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700113
114 // create new output stream
115 AudioStreamInGeneric* in = new AudioStreamInGeneric();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800116 status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate);
117 if (status) {
118 *status = lStatus;
119 }
120 if (lStatus == NO_ERROR) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700121 mInput = in;
122 } else {
123 delete in;
124 }
125 return mInput;
126}
127
128void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) {
129 if (in == mInput) mInput = 0;
130}
131
132status_t AudioHardwareGeneric::setVoiceVolume(float v)
133{
134 // Implement: set voice volume
135 return NO_ERROR;
136}
137
138status_t AudioHardwareGeneric::setMasterVolume(float v)
139{
140 // Implement: set master volume
141 // return error - software mixer will handle it
142 return INVALID_OPERATION;
143}
144
145status_t AudioHardwareGeneric::setMicMute(bool state)
146{
147 mMicMute = state;
148 return NO_ERROR;
149}
150
151status_t AudioHardwareGeneric::getMicMute(bool* state)
152{
153 *state = mMicMute;
154 return NO_ERROR;
155}
156
157status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
158{
159 const size_t SIZE = 256;
160 char buffer[SIZE];
161 String8 result;
162 result.append("AudioHardwareGeneric::dumpInternals\n");
163 snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
164 result.append(buffer);
165 ::write(fd, result.string(), result.size());
166 return NO_ERROR;
167}
168
169status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
170{
171 dumpInternals(fd, args);
172 if (mInput) {
173 mInput->dump(fd, args);
174 }
175 if (mOutput) {
176 mOutput->dump(fd, args);
177 }
178 return NO_ERROR;
179}
180
181// ----------------------------------------------------------------------------
182
183status_t AudioStreamOutGeneric::set(
184 AudioHardwareGeneric *hw,
185 int fd,
186 int format,
187 int channels,
188 uint32_t rate)
189{
190 // fix up defaults
191 if (format == 0) format = AudioSystem::PCM_16_BIT;
192 if (channels == 0) channels = channelCount();
193 if (rate == 0) rate = sampleRate();
194
195 // check values
196 if ((format != AudioSystem::PCM_16_BIT) ||
197 (channels != channelCount()) ||
198 (rate != sampleRate()))
199 return BAD_VALUE;
200
201 mAudioHardware = hw;
202 mFd = fd;
203 return NO_ERROR;
204}
205
206AudioStreamOutGeneric::~AudioStreamOutGeneric()
207{
208 if (mAudioHardware)
209 mAudioHardware->closeOutputStream(this);
210}
211
212ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
213{
214 Mutex::Autolock _l(mLock);
215 return ssize_t(::write(mFd, buffer, bytes));
216}
217
218status_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