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