1/*
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
35#include <hardware_legacy/AudioSystemLegacy.h>
36
37namespace android_audio_legacy {
38
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;
276    LOGV("setParameters() %s", keyValuePairs.string());
277
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
299    LOGV("getParameters() %s", param.toString().string());
300    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;
321    LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
322    // check values
323    if ((*pFormat != format()) ||
324        (*pChannels != channels()) ||
325        (*pRate != sampleRate())) {
326        LOGE("Error opening input channel");
327        *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) {
347        LOGE("Attempt to read from unopened device");
348        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;
384    LOGV("setParameters() %s", keyValuePairs.string());
385
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
407    LOGV("getParameters() %s", param.toString().string());
408    return param.toString();
409}
410
411// ----------------------------------------------------------------------------
412
413}; // namespace android
414