• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/libaudio


Commit MetaInfo

Revisión2d37c6cf645f282661995c21106920ef587b1034 (tree)
Tiempo2012-01-23 04:20:37
AutorChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Log Message

audio hal for ics-x86

Modified from Linaro project.

Cambiar Resumen

Diferencia incremental

--- a/Android.mk
+++ b/Android.mk
@@ -11,3 +11,35 @@
1111 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212 # See the License for the specific language governing permissions and
1313 # limitations under the License.
14+
15+ifeq ($(strip $(BOARD_USES_ALSA_AUDIO)),true)
16+
17+LOCAL_PATH := $(call my-dir)
18+
19+include $(CLEAR_VARS)
20+
21+LOCAL_MODULE := audio.primary.default
22+LOCAL_MODULE_TAGS := optional
23+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
24+
25+LOCAL_SHARED_LIBRARIES := \
26+ libdl \
27+ libmedia \
28+ libutils \
29+ libcutils \
30+ libhardware_legacy
31+
32+LOCAL_SRC_FILES := \
33+ alsa_pcm.c \
34+ alsa_mixer.c \
35+ AudioHardware.cpp
36+
37+LOCAL_STATIC_LIBRARIES := \
38+ libmedia_helper
39+
40+LOCAL_WHOLE_STATIC_LIBRARIES := \
41+ libaudiohw_legacy
42+
43+include $(BUILD_SHARED_LIBRARY)
44+
45+endif
--- /dev/null
+++ b/AudioHardware.cpp
@@ -0,0 +1,1811 @@
1+/*
2+** Copyright 2011, The Android Open-Source Project
3+**
4+** Licensed under the Apache License, Version 2.0 (the "License");
5+** you may not use this file except in compliance with the License.
6+** You may obtain a copy of the License at
7+**
8+** http://www.apache.org/licenses/LICENSE-2.0
9+**
10+** Unless required by applicable law or agreed to in writing, software
11+** distributed under the License is distributed on an "AS IS" BASIS,
12+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+** See the License for the specific language governing permissions and
14+** limitations under the License.
15+*/
16+
17+#include <math.h>
18+
19+//#define LOG_NDEBUG 0
20+
21+#define LOG_TAG "AudioHardware"
22+
23+#include <utils/Log.h>
24+#include <utils/String8.h>
25+
26+#include <stdio.h>
27+#include <unistd.h>
28+#include <sys/ioctl.h>
29+#include <sys/types.h>
30+#include <sys/stat.h>
31+#include <sys/resource.h>
32+#include <dlfcn.h>
33+#include <fcntl.h>
34+
35+#include "AudioHardware.h"
36+#include <media/AudioRecord.h>
37+#include <hardware_legacy/power.h>
38+
39+#include "alsa_audio.h"
40+
41+
42+namespace android_audio_legacy {
43+
44+const uint32_t AudioHardware::inputSamplingRates[] = {
45+ 8000, 11025, 16000, 22050, 44100
46+};
47+
48+// trace driver operations for dump
49+//
50+#define DRIVER_TRACE
51+
52+enum {
53+ DRV_NONE,
54+ DRV_PCM_OPEN,
55+ DRV_PCM_CLOSE,
56+ DRV_PCM_WRITE,
57+ DRV_PCM_READ,
58+ DRV_MIXER_OPEN,
59+ DRV_MIXER_CLOSE,
60+ DRV_MIXER_GET,
61+ DRV_MIXER_SEL
62+};
63+
64+#ifdef DRIVER_TRACE
65+#define TRACE_DRIVER_IN(op) mDriverOp = op;
66+#define TRACE_DRIVER_OUT mDriverOp = DRV_NONE;
67+#else
68+#define TRACE_DRIVER_IN(op)
69+#define TRACE_DRIVER_OUT
70+#endif
71+
72+// ----------------------------------------------------------------------------
73+
74+AudioHardware::AudioHardware() :
75+ mInit(false),
76+ mMicMute(false),
77+ mPcm(NULL),
78+ mMixer(NULL),
79+ mPcmOpenCnt(0),
80+ mMixerOpenCnt(0),
81+ mInCallAudioMode(false),
82+ mInputSource("Default"),
83+ mBluetoothNrec(true),
84+ mActivatedCP(false),
85+ mDriverOp(DRV_NONE)
86+{
87+ mInit = true;
88+}
89+
90+AudioHardware::~AudioHardware()
91+{
92+ for (size_t index = 0; index < mInputs.size(); index++) {
93+ closeInputStream(mInputs[index].get());
94+ }
95+ mInputs.clear();
96+ closeOutputStream((AudioStreamOut*)mOutput.get());
97+
98+ if (mMixer) {
99+ TRACE_DRIVER_IN(DRV_MIXER_CLOSE)
100+ mixer_close(mMixer);
101+ TRACE_DRIVER_OUT
102+ }
103+ if (mPcm) {
104+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
105+ pcm_close(mPcm);
106+ TRACE_DRIVER_OUT
107+ }
108+
109+ mInit = false;
110+}
111+
112+status_t AudioHardware::initCheck()
113+{
114+ return mInit ? NO_ERROR : NO_INIT;
115+}
116+
117+AudioStreamOut* AudioHardware::openOutputStream(
118+ uint32_t devices, int *format, uint32_t *channels,
119+ uint32_t *sampleRate, status_t *status)
120+{
121+ sp <AudioStreamOutALSA> out;
122+ status_t rc;
123+
124+ { // scope for the lock
125+ Mutex::Autolock lock(mLock);
126+
127+ // only one output stream allowed
128+ if (mOutput != 0) {
129+ if (status) {
130+ *status = INVALID_OPERATION;
131+ }
132+ return NULL;
133+ }
134+
135+ out = new AudioStreamOutALSA();
136+
137+ rc = out->set(this, devices, format, channels, sampleRate);
138+ if (rc == NO_ERROR) {
139+ mOutput = out;
140+ }
141+ }
142+
143+ if (rc != NO_ERROR) {
144+ if (out != 0) {
145+ out.clear();
146+ }
147+ }
148+ if (status) {
149+ *status = rc;
150+ }
151+
152+ return out.get();
153+}
154+
155+void AudioHardware::closeOutputStream(AudioStreamOut* out) {
156+ sp <AudioStreamOutALSA> spOut;
157+ {
158+ Mutex::Autolock lock(mLock);
159+ if (mOutput == 0 || mOutput.get() != out) {
160+ LOGW("Attempt to close invalid output stream");
161+ return;
162+ }
163+ spOut = mOutput;
164+ mOutput.clear();
165+ }
166+ spOut.clear();
167+}
168+
169+AudioStreamIn* AudioHardware::openInputStream(
170+ uint32_t devices, int *format, uint32_t *channels,
171+ uint32_t *sampleRate, status_t *status,
172+ AudioSystem::audio_in_acoustics acoustic_flags)
173+{
174+ // check for valid input source
175+ if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
176+ if (status) {
177+ *status = BAD_VALUE;
178+ }
179+ return NULL;
180+ }
181+
182+ status_t rc = NO_ERROR;
183+ sp <AudioStreamInALSA> in;
184+
185+ { // scope for the lock
186+ Mutex::Autolock lock(mLock);
187+
188+ in = new AudioStreamInALSA();
189+ rc = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
190+ if (rc == NO_ERROR) {
191+ mInputs.add(in);
192+ }
193+ }
194+
195+ if (rc != NO_ERROR) {
196+ if (in != 0) {
197+ in.clear();
198+ }
199+ }
200+ if (status) {
201+ *status = rc;
202+ }
203+
204+ LOGV("AudioHardware::openInputStream()%p", in.get());
205+ return in.get();
206+}
207+
208+void AudioHardware::closeInputStream(AudioStreamIn* in) {
209+
210+ sp<AudioStreamInALSA> spIn;
211+ {
212+ Mutex::Autolock lock(mLock);
213+
214+ ssize_t index = mInputs.indexOf((AudioStreamInALSA *)in);
215+ if (index < 0) {
216+ LOGW("Attempt to close invalid input stream");
217+ return;
218+ }
219+ spIn = mInputs[index];
220+ mInputs.removeAt(index);
221+ }
222+ LOGV("AudioHardware::closeInputStream()%p", in);
223+ spIn.clear();
224+}
225+
226+
227+status_t AudioHardware::setMode(int mode)
228+{
229+ sp<AudioStreamOutALSA> spOut;
230+ sp<AudioStreamInALSA> spIn;
231+ status_t status;
232+
233+ // bump thread priority to speed up mutex acquisition
234+ int priority = getpriority(PRIO_PROCESS, 0);
235+ setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_URGENT_AUDIO);
236+
237+ // Mutex acquisition order is always out -> in -> hw
238+ AutoMutex lock(mLock);
239+
240+ spOut = mOutput;
241+ while (spOut != 0) {
242+ if (!spOut->checkStandby()) {
243+ int cnt = spOut->standbyCnt();
244+ mLock.unlock();
245+ spOut->lock();
246+ mLock.lock();
247+ // make sure that another thread did not change output state while the
248+ // mutex is released
249+ if ((spOut == mOutput) && (cnt == spOut->standbyCnt())) {
250+ break;
251+ }
252+ spOut->unlock();
253+ spOut = mOutput;
254+ } else {
255+ spOut.clear();
256+ }
257+ }
258+ // spOut is not 0 here only if the output is active
259+
260+ spIn = getActiveInput_l();
261+ while (spIn != 0) {
262+ int cnt = spIn->standbyCnt();
263+ mLock.unlock();
264+ spIn->lock();
265+ mLock.lock();
266+ // make sure that another thread did not change input state while the
267+ // mutex is released
268+ if ((spIn == getActiveInput_l()) && (cnt == spIn->standbyCnt())) {
269+ break;
270+ }
271+ spIn->unlock();
272+ spIn = getActiveInput_l();
273+ }
274+ // spIn is not 0 here only if the input is active
275+
276+ setpriority(PRIO_PROCESS, 0, priority);
277+
278+ int prevMode = mMode;
279+ status = AudioHardwareBase::setMode(mode);
280+ LOGV("setMode() : new %d, old %d", mMode, prevMode);
281+ if (status == NO_ERROR) {
282+ if (mMode == AudioSystem::MODE_IN_CALL && !mInCallAudioMode) {
283+ if (spOut != 0) {
284+ LOGV("setMode() in call force output standby");
285+ spOut->doStandby_l();
286+ }
287+ if (spIn != 0) {
288+ LOGV("setMode() in call force input standby");
289+ spIn->doStandby_l();
290+ }
291+
292+ LOGV("setMode() openPcmOut_l()");
293+ openPcmOut_l();
294+ openMixer_l();
295+ setInputSource_l(String8("Default"));
296+ mInCallAudioMode = true;
297+ }
298+ if (mMode == AudioSystem::MODE_NORMAL && mInCallAudioMode) {
299+ setInputSource_l(mInputSource);
300+ if (mMixer != NULL) {
301+ TRACE_DRIVER_IN(DRV_MIXER_GET)
302+ struct mixer_ctl *ctl= mixer_get_control(mMixer, "Playback Path", 0);
303+ TRACE_DRIVER_OUT
304+ if (ctl != NULL) {
305+ LOGV("setMode() reset Playback Path to RCV");
306+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
307+ mixer_ctl_select(ctl, "RCV");
308+ TRACE_DRIVER_OUT
309+ }
310+ }
311+ LOGV("setMode() closePcmOut_l()");
312+ closeMixer_l();
313+ closePcmOut_l();
314+
315+ if (spOut != 0) {
316+ LOGV("setMode() off call force output standby");
317+ spOut->doStandby_l();
318+ }
319+ if (spIn != 0) {
320+ LOGV("setMode() off call force input standby");
321+ spIn->doStandby_l();
322+ }
323+
324+ mInCallAudioMode = false;
325+ }
326+
327+ if (mMode == AudioSystem::MODE_NORMAL) {
328+ if(mActivatedCP)
329+ mActivatedCP = false;
330+ }
331+ }
332+
333+ if (spIn != 0) {
334+ spIn->unlock();
335+ }
336+ if (spOut != 0) {
337+ spOut->unlock();
338+ }
339+
340+ return status;
341+}
342+
343+status_t AudioHardware::setMicMute(bool state)
344+{
345+ LOGV("setMicMute(%d) mMicMute %d", state, mMicMute);
346+ sp<AudioStreamInALSA> spIn;
347+ {
348+ AutoMutex lock(mLock);
349+ if (mMicMute != state) {
350+ mMicMute = state;
351+ if (mMode != AudioSystem::MODE_IN_CALL) {
352+ spIn = getActiveInput_l();
353+ }
354+ }
355+ }
356+
357+ if (spIn != 0) {
358+ spIn->standby();
359+ }
360+
361+ return NO_ERROR;
362+}
363+
364+status_t AudioHardware::getMicMute(bool* state)
365+{
366+ *state = mMicMute;
367+ return NO_ERROR;
368+}
369+
370+status_t AudioHardware::setParameters(const String8& keyValuePairs)
371+{
372+ AudioParameter param = AudioParameter(keyValuePairs);
373+ String8 value;
374+ String8 key;
375+ const char BT_NREC_KEY[] = "bt_headset_nrec";
376+ const char BT_NREC_VALUE_ON[] = "on";
377+
378+ key = String8(BT_NREC_KEY);
379+ if (param.get(key, value) == NO_ERROR) {
380+ if (value == BT_NREC_VALUE_ON) {
381+ mBluetoothNrec = true;
382+ } else {
383+ mBluetoothNrec = false;
384+ LOGD("Turning noise reduction and echo cancellation off for BT "
385+ "headset");
386+ }
387+ }
388+
389+ return NO_ERROR;
390+}
391+
392+String8 AudioHardware::getParameters(const String8& keys)
393+{
394+ AudioParameter request = AudioParameter(keys);
395+ AudioParameter reply = AudioParameter();
396+
397+ LOGV("getParameters() %s", keys.string());
398+
399+ return reply.toString();
400+}
401+
402+size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
403+{
404+ if (format != AudioSystem::PCM_16_BIT) {
405+ LOGW("getInputBufferSize bad format: %d", format);
406+ return 0;
407+ }
408+ if (channelCount < 1 || channelCount > 2) {
409+ LOGW("getInputBufferSize bad channel count: %d", channelCount);
410+ return 0;
411+ }
412+ if (sampleRate != 8000 && sampleRate != 11025 && sampleRate != 16000 &&
413+ sampleRate != 22050 && sampleRate != 44100) {
414+ LOGW("getInputBufferSize bad sample rate: %d", sampleRate);
415+ return 0;
416+ }
417+
418+ return AudioStreamInALSA::getBufferSize(sampleRate, channelCount);
419+}
420+
421+
422+status_t AudioHardware::setVoiceVolume(float volume)
423+{
424+ LOGD("### setVoiceVolume: %f", volume);
425+ return NO_ERROR;
426+}
427+
428+status_t AudioHardware::setMasterVolume(float volume)
429+{
430+ LOGV("Set master volume to %f.\n", volume);
431+ // We return an error code here to let the audioflinger do in-software
432+ // volume on top of the maximum volume that we set through the SND API.
433+ // return error - software mixer will handle it
434+ return -1;
435+}
436+
437+static const int kDumpLockRetries = 50;
438+static const int kDumpLockSleep = 20000;
439+
440+static bool tryLock(Mutex& mutex)
441+{
442+ bool locked = false;
443+ for (int i = 0; i < kDumpLockRetries; ++i) {
444+ if (mutex.tryLock() == NO_ERROR) {
445+ locked = true;
446+ break;
447+ }
448+ usleep(kDumpLockSleep);
449+ }
450+ return locked;
451+}
452+
453+status_t AudioHardware::dump(int fd, const Vector<String16>& args)
454+{
455+ const size_t SIZE = 256;
456+ char buffer[SIZE];
457+ String8 result;
458+
459+ bool locked = tryLock(mLock);
460+ if (!locked) {
461+ snprintf(buffer, SIZE, "\n\tAudioHardware maybe deadlocked\n");
462+ } else {
463+ mLock.unlock();
464+ }
465+
466+ snprintf(buffer, SIZE, "\tInit %s\n", (mInit) ? "OK" : "Failed");
467+ result.append(buffer);
468+ snprintf(buffer, SIZE, "\tMic Mute %s\n", (mMicMute) ? "ON" : "OFF");
469+ result.append(buffer);
470+ snprintf(buffer, SIZE, "\tmPcm: %p\n", mPcm);
471+ result.append(buffer);
472+ snprintf(buffer, SIZE, "\tmPcmOpenCnt: %d\n", mPcmOpenCnt);
473+ result.append(buffer);
474+ snprintf(buffer, SIZE, "\tmMixer: %p\n", mMixer);
475+ result.append(buffer);
476+ snprintf(buffer, SIZE, "\tmMixerOpenCnt: %d\n", mMixerOpenCnt);
477+ result.append(buffer);
478+ snprintf(buffer, SIZE, "\tIn Call Audio Mode %s\n",
479+ (mInCallAudioMode) ? "ON" : "OFF");
480+ result.append(buffer);
481+ snprintf(buffer, SIZE, "\tInput source %s\n", mInputSource.string());
482+ result.append(buffer);
483+ snprintf(buffer, SIZE, "\tCP %s\n",
484+ (mActivatedCP) ? "Activated" : "Deactivated");
485+ result.append(buffer);
486+ snprintf(buffer, SIZE, "\tmDriverOp: %d\n", mDriverOp);
487+ result.append(buffer);
488+
489+ snprintf(buffer, SIZE, "\n\tmOutput %p dump:\n", mOutput.get());
490+ result.append(buffer);
491+ write(fd, result.string(), result.size());
492+ if (mOutput != 0) {
493+ mOutput->dump(fd, args);
494+ }
495+
496+ snprintf(buffer, SIZE, "\n\t%d inputs opened:\n", mInputs.size());
497+ write(fd, buffer, strlen(buffer));
498+ for (size_t i = 0; i < mInputs.size(); i++) {
499+ snprintf(buffer, SIZE, "\t- input %d dump:\n", i);
500+ write(fd, buffer, strlen(buffer));
501+ mInputs[i]->dump(fd, args);
502+ }
503+
504+ return NO_ERROR;
505+}
506+
507+status_t AudioHardware::setIncallPath_l(uint32_t device)
508+{
509+ LOGV("setIncallPath_l: device %x", device);
510+ return NO_ERROR;
511+}
512+
513+struct pcm *AudioHardware::openPcmOut_l()
514+{
515+ LOGD("openPcmOut_l() mPcmOpenCnt: %d", mPcmOpenCnt);
516+ if (mPcmOpenCnt++ == 0) {
517+ if (mPcm != NULL) {
518+ LOGE("openPcmOut_l() mPcmOpenCnt == 0 and mPcm == %p\n", mPcm);
519+ mPcmOpenCnt--;
520+ return NULL;
521+ }
522+ unsigned flags = PCM_OUT;
523+
524+ flags |= (AUDIO_HW_OUT_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
525+ flags |= (AUDIO_HW_OUT_PERIOD_CNT - PCM_PERIOD_CNT_MIN) << PCM_PERIOD_CNT_SHIFT;
526+
527+ TRACE_DRIVER_IN(DRV_PCM_OPEN)
528+ mPcm = pcm_open(flags);
529+ TRACE_DRIVER_OUT
530+ if (!pcm_ready(mPcm)) {
531+ LOGE("openPcmOut_l() cannot open pcm_out driver: %s\n", pcm_error(mPcm));
532+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
533+ pcm_close(mPcm);
534+ TRACE_DRIVER_OUT
535+ mPcmOpenCnt--;
536+ mPcm = NULL;
537+ }
538+ }
539+ return mPcm;
540+}
541+
542+void AudioHardware::closePcmOut_l()
543+{
544+ LOGD("closePcmOut_l() mPcmOpenCnt: %d", mPcmOpenCnt);
545+ if (mPcmOpenCnt == 0) {
546+ LOGE("closePcmOut_l() mPcmOpenCnt == 0");
547+ return;
548+ }
549+
550+ if (--mPcmOpenCnt == 0) {
551+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
552+ pcm_close(mPcm);
553+ TRACE_DRIVER_OUT
554+ mPcm = NULL;
555+ }
556+}
557+
558+struct mixer *AudioHardware::openMixer_l()
559+{
560+ LOGV("openMixer_l() mMixerOpenCnt: %d", mMixerOpenCnt);
561+ if (mMixerOpenCnt++ == 0) {
562+ if (mMixer != NULL) {
563+ LOGE("openMixer_l() mMixerOpenCnt == 0 and mMixer == %p\n", mMixer);
564+ mMixerOpenCnt--;
565+ return NULL;
566+ }
567+ TRACE_DRIVER_IN(DRV_MIXER_OPEN)
568+ mMixer = mixer_open();
569+ TRACE_DRIVER_OUT
570+ if (mMixer == NULL) {
571+ LOGE("openMixer_l() cannot open mixer");
572+ mMixerOpenCnt--;
573+ return NULL;
574+ }
575+ }
576+ return mMixer;
577+}
578+
579+void AudioHardware::closeMixer_l()
580+{
581+ LOGV("closeMixer_l() mMixerOpenCnt: %d", mMixerOpenCnt);
582+ if (mMixerOpenCnt == 0) {
583+ LOGE("closeMixer_l() mMixerOpenCnt == 0");
584+ return;
585+ }
586+
587+ if (--mMixerOpenCnt == 0) {
588+ TRACE_DRIVER_IN(DRV_MIXER_CLOSE)
589+ mixer_close(mMixer);
590+ TRACE_DRIVER_OUT
591+ mMixer = NULL;
592+ }
593+}
594+
595+const char *AudioHardware::getOutputRouteFromDevice(uint32_t device)
596+{
597+ switch (device) {
598+ case AudioSystem::DEVICE_OUT_EARPIECE:
599+ return "RCV";
600+ case AudioSystem::DEVICE_OUT_SPEAKER:
601+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_SPK";
602+ else return "SPK";
603+ case AudioSystem::DEVICE_OUT_WIRED_HEADPHONE:
604+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_NO_MIC";
605+ else return "HP_NO_MIC";
606+ case AudioSystem::DEVICE_OUT_WIRED_HEADSET:
607+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_HP";
608+ else return "HP";
609+ case (AudioSystem::DEVICE_OUT_SPEAKER|AudioSystem::DEVICE_OUT_WIRED_HEADPHONE):
610+ case (AudioSystem::DEVICE_OUT_SPEAKER|AudioSystem::DEVICE_OUT_WIRED_HEADSET):
611+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_SPK_HP";
612+ else return "SPK_HP";
613+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO:
614+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
615+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
616+ return "BT";
617+ default:
618+ return "OFF";
619+ }
620+}
621+
622+const char *AudioHardware::getVoiceRouteFromDevice(uint32_t device)
623+{
624+ switch (device) {
625+ case AudioSystem::DEVICE_OUT_EARPIECE:
626+ return "RCV";
627+ case AudioSystem::DEVICE_OUT_SPEAKER:
628+ return "SPK";
629+ case AudioSystem::DEVICE_OUT_WIRED_HEADPHONE:
630+ return "HP_NO_MIC";
631+ case AudioSystem::DEVICE_OUT_WIRED_HEADSET:
632+ return "HP";
633+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO:
634+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
635+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
636+ return "BT";
637+ default:
638+ return "OFF";
639+ }
640+}
641+
642+const char *AudioHardware::getInputRouteFromDevice(uint32_t device)
643+{
644+ if (mMicMute) {
645+ return "MIC OFF";
646+ }
647+
648+ switch (device) {
649+ case AudioSystem::DEVICE_IN_BUILTIN_MIC:
650+ return "Main Mic";
651+ case AudioSystem::DEVICE_IN_WIRED_HEADSET:
652+ return "Hands Free Mic";
653+ case AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET:
654+ return "BT Sco Mic";
655+ default:
656+ return "MIC OFF";
657+ }
658+}
659+
660+uint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
661+{
662+ uint32_t i;
663+ uint32_t prevDelta;
664+ uint32_t delta;
665+
666+ for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
667+ delta = abs(sampleRate - inputSamplingRates[i]);
668+ if (delta > prevDelta) break;
669+ }
670+ // i is always > 0 here
671+ return inputSamplingRates[i-1];
672+}
673+
674+// getActiveInput_l() must be called with mLock held
675+sp <AudioHardware::AudioStreamInALSA> AudioHardware::getActiveInput_l()
676+{
677+ sp< AudioHardware::AudioStreamInALSA> spIn;
678+
679+ for (size_t i = 0; i < mInputs.size(); i++) {
680+ // return first input found not being in standby mode
681+ // as only one input can be in this state
682+ if (!mInputs[i]->checkStandby()) {
683+ spIn = mInputs[i];
684+ break;
685+ }
686+ }
687+
688+ return spIn;
689+}
690+
691+status_t AudioHardware::setInputSource_l(String8 source)
692+{
693+ LOGV("setInputSource_l(%s)", source.string());
694+ if (source != mInputSource) {
695+ if ((source == "Default") || (mMode != AudioSystem::MODE_IN_CALL)) {
696+ if (mMixer) {
697+ TRACE_DRIVER_IN(DRV_MIXER_GET)
698+ struct mixer_ctl *ctl= mixer_get_control(mMixer, "Input Source", 0);
699+ TRACE_DRIVER_OUT
700+ if (ctl == NULL) {
701+ return NO_INIT;
702+ }
703+ LOGV("mixer_ctl_select, Input Source, (%s)", source.string());
704+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
705+ mixer_ctl_select(ctl, source.string());
706+ TRACE_DRIVER_OUT
707+ }
708+ }
709+ mInputSource = source;
710+ }
711+
712+ return NO_ERROR;
713+}
714+
715+
716+//------------------------------------------------------------------------------
717+// AudioStreamOutALSA
718+//------------------------------------------------------------------------------
719+
720+AudioHardware::AudioStreamOutALSA::AudioStreamOutALSA() :
721+ mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
722+ mStandby(true), mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS),
723+ mSampleRate(AUDIO_HW_OUT_SAMPLERATE), mBufferSize(AUDIO_HW_OUT_PERIOD_BYTES),
724+ mDriverOp(DRV_NONE), mStandbyCnt(0)
725+{
726+}
727+
728+status_t AudioHardware::AudioStreamOutALSA::set(
729+ AudioHardware* hw, uint32_t devices, int *pFormat,
730+ uint32_t *pChannels, uint32_t *pRate)
731+{
732+ int lFormat = pFormat ? *pFormat : 0;
733+ uint32_t lChannels = pChannels ? *pChannels : 0;
734+ uint32_t lRate = pRate ? *pRate : 0;
735+
736+ mHardware = hw;
737+ mDevices = devices;
738+
739+ // fix up defaults
740+ if (lFormat == 0) lFormat = format();
741+ if (lChannels == 0) lChannels = channels();
742+ if (lRate == 0) lRate = sampleRate();
743+
744+ // check values
745+ if ((lFormat != format()) ||
746+ (lChannels != channels()) ||
747+ (lRate != sampleRate())) {
748+ if (pFormat) *pFormat = format();
749+ if (pChannels) *pChannels = channels();
750+ if (pRate) *pRate = sampleRate();
751+ return BAD_VALUE;
752+ }
753+
754+ if (pFormat) *pFormat = lFormat;
755+ if (pChannels) *pChannels = lChannels;
756+ if (pRate) *pRate = lRate;
757+
758+ mChannels = lChannels;
759+ mSampleRate = lRate;
760+ mBufferSize = AUDIO_HW_OUT_PERIOD_BYTES;
761+
762+ return NO_ERROR;
763+}
764+
765+AudioHardware::AudioStreamOutALSA::~AudioStreamOutALSA()
766+{
767+ standby();
768+}
769+
770+ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes)
771+{
772+ // LOGV("AudioStreamOutALSA::write(%p, %u)", buffer, bytes);
773+ status_t status = NO_INIT;
774+ const uint8_t* p = static_cast<const uint8_t*>(buffer);
775+ int ret;
776+
777+ if (mHardware == NULL) return NO_INIT;
778+
779+ { // scope for the lock
780+
781+ AutoMutex lock(mLock);
782+
783+ if (mStandby) {
784+ AutoMutex hwLock(mHardware->lock());
785+
786+ LOGD("AudioHardware pcm playback is exiting standby.");
787+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
788+
789+ sp<AudioStreamInALSA> spIn = mHardware->getActiveInput_l();
790+ while (spIn != 0) {
791+ int cnt = spIn->standbyCnt();
792+ mHardware->lock().unlock();
793+ // Mutex acquisition order is always out -> in -> hw
794+ spIn->lock();
795+ mHardware->lock().lock();
796+ // make sure that another thread did not change input state
797+ // while the mutex is released
798+ if ((spIn == mHardware->getActiveInput_l()) &&
799+ (cnt == spIn->standbyCnt())) {
800+ LOGV("AudioStreamOutALSA::write() force input standby");
801+ spIn->close_l();
802+ break;
803+ }
804+ spIn->unlock();
805+ spIn = mHardware->getActiveInput_l();
806+ }
807+ // spIn is not 0 here only if the input was active and has been
808+ // closed above
809+
810+ // open output before input
811+ open_l();
812+
813+ if (spIn != 0) {
814+ if (spIn->open_l() != NO_ERROR) {
815+ spIn->doStandby_l();
816+ }
817+ spIn->unlock();
818+ }
819+ if (mPcm == NULL) {
820+ release_wake_lock("AudioOutLock");
821+ goto Error;
822+ }
823+ mStandby = false;
824+ }
825+
826+ TRACE_DRIVER_IN(DRV_PCM_WRITE)
827+ ret = pcm_write(mPcm,(void*) p, bytes);
828+ TRACE_DRIVER_OUT
829+
830+ if (ret == 0) {
831+ return bytes;
832+ }
833+ LOGW("write error: %d", errno);
834+ status = -errno;
835+ }
836+Error:
837+
838+ standby();
839+
840+ // Simulate audio output timing in case of error
841+ usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
842+
843+ return status;
844+}
845+
846+status_t AudioHardware::AudioStreamOutALSA::standby()
847+{
848+ if (mHardware == NULL) return NO_INIT;
849+
850+ AutoMutex lock(mLock);
851+
852+ { // scope for the AudioHardware lock
853+ AutoMutex hwLock(mHardware->lock());
854+
855+ doStandby_l();
856+ }
857+
858+ return NO_ERROR;
859+}
860+
861+void AudioHardware::AudioStreamOutALSA::doStandby_l()
862+{
863+ mStandbyCnt++;
864+
865+ if (!mStandby) {
866+ LOGD("AudioHardware pcm playback is going to standby.");
867+ release_wake_lock("AudioOutLock");
868+ mStandby = true;
869+ }
870+
871+ close_l();
872+}
873+
874+void AudioHardware::AudioStreamOutALSA::close_l()
875+{
876+ if (mMixer) {
877+ mHardware->closeMixer_l();
878+ mMixer = NULL;
879+ mRouteCtl = NULL;
880+ }
881+ if (mPcm) {
882+ mHardware->closePcmOut_l();
883+ mPcm = NULL;
884+ }
885+}
886+
887+status_t AudioHardware::AudioStreamOutALSA::open_l()
888+{
889+ LOGV("open pcm_out driver");
890+ mPcm = mHardware->openPcmOut_l();
891+ if (mPcm == NULL) {
892+ return NO_INIT;
893+ }
894+
895+ mMixer = mHardware->openMixer_l();
896+ if (mMixer) {
897+ LOGV("open playback normal");
898+ TRACE_DRIVER_IN(DRV_MIXER_GET)
899+ mRouteCtl = mixer_get_control(mMixer, "Playback Path", 0);
900+ TRACE_DRIVER_OUT
901+ }
902+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
903+ const char *route = mHardware->getOutputRouteFromDevice(mDevices);
904+ LOGV("write() wakeup setting route %s", route);
905+ if (mRouteCtl) {
906+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
907+ mixer_ctl_select(mRouteCtl, route);
908+ TRACE_DRIVER_OUT
909+ }
910+ }
911+ return NO_ERROR;
912+}
913+
914+status_t AudioHardware::AudioStreamOutALSA::dump(int fd, const Vector<String16>& args)
915+{
916+ const size_t SIZE = 256;
917+ char buffer[SIZE];
918+ String8 result;
919+
920+ bool locked = tryLock(mLock);
921+ if (!locked) {
922+ snprintf(buffer, SIZE, "\n\t\tAudioStreamOutALSA maybe deadlocked\n");
923+ } else {
924+ mLock.unlock();
925+ }
926+
927+ snprintf(buffer, SIZE, "\t\tmHardware: %p\n", mHardware);
928+ result.append(buffer);
929+ snprintf(buffer, SIZE, "\t\tmPcm: %p\n", mPcm);
930+ result.append(buffer);
931+ snprintf(buffer, SIZE, "\t\tmMixer: %p\n", mMixer);
932+ result.append(buffer);
933+ snprintf(buffer, SIZE, "\t\tmRouteCtl: %p\n", mRouteCtl);
934+ result.append(buffer);
935+ snprintf(buffer, SIZE, "\t\tStandby %s\n", (mStandby) ? "ON" : "OFF");
936+ result.append(buffer);
937+ snprintf(buffer, SIZE, "\t\tmDevices: 0x%08x\n", mDevices);
938+ result.append(buffer);
939+ snprintf(buffer, SIZE, "\t\tmChannels: 0x%08x\n", mChannels);
940+ result.append(buffer);
941+ snprintf(buffer, SIZE, "\t\tmSampleRate: %d\n", mSampleRate);
942+ result.append(buffer);
943+ snprintf(buffer, SIZE, "\t\tmBufferSize: %d\n", mBufferSize);
944+ result.append(buffer);
945+ snprintf(buffer, SIZE, "\t\tmDriverOp: %d\n", mDriverOp);
946+ result.append(buffer);
947+
948+ ::write(fd, result.string(), result.size());
949+
950+ return NO_ERROR;
951+}
952+
953+bool AudioHardware::AudioStreamOutALSA::checkStandby()
954+{
955+ return mStandby;
956+}
957+
958+status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
959+{
960+ AudioParameter param = AudioParameter(keyValuePairs);
961+ status_t status = NO_ERROR;
962+ int device;
963+ LOGD("AudioStreamOutALSA::setParameters() %s", keyValuePairs.string());
964+
965+ if (mHardware == NULL) return NO_INIT;
966+
967+ {
968+ AutoMutex lock(mLock);
969+
970+ if (param.getInt(String8(AudioParameter::keyRouting), device) == NO_ERROR)
971+ {
972+ AutoMutex hwLock(mHardware->lock());
973+
974+ if (mDevices != (uint32_t)device) {
975+ mDevices = (uint32_t)device;
976+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
977+ doStandby_l();
978+ }
979+ }
980+ if (mHardware->mode() == AudioSystem::MODE_IN_CALL) {
981+ mHardware->setIncallPath_l(device);
982+ }
983+ param.remove(String8(AudioParameter::keyRouting));
984+ }
985+ }
986+
987+ if (param.size()) {
988+ status = BAD_VALUE;
989+ }
990+
991+
992+ return status;
993+
994+}
995+
996+String8 AudioHardware::AudioStreamOutALSA::getParameters(const String8& keys)
997+{
998+ AudioParameter param = AudioParameter(keys);
999+ String8 value;
1000+ String8 key = String8(AudioParameter::keyRouting);
1001+
1002+ if (param.get(key, value) == NO_ERROR) {
1003+ param.addInt(key, (int)mDevices);
1004+ }
1005+
1006+ LOGV("AudioStreamOutALSA::getParameters() %s", param.toString().string());
1007+ return param.toString();
1008+}
1009+
1010+status_t AudioHardware::AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrames)
1011+{
1012+ //TODO
1013+ return INVALID_OPERATION;
1014+}
1015+
1016+//------------------------------------------------------------------------------
1017+// AudioStreamInALSA
1018+//------------------------------------------------------------------------------
1019+
1020+AudioHardware::AudioStreamInALSA::AudioStreamInALSA() :
1021+ mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
1022+ mStandby(true), mDevices(0), mChannels(AUDIO_HW_IN_CHANNELS), mChannelCount(1),
1023+ mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_PERIOD_BYTES),
1024+ mDownSampler(NULL), mReadStatus(NO_ERROR), mDriverOp(DRV_NONE),
1025+ mStandbyCnt(0)
1026+{
1027+}
1028+
1029+status_t AudioHardware::AudioStreamInALSA::set(
1030+ AudioHardware* hw, uint32_t devices, int *pFormat,
1031+ uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics)
1032+{
1033+ if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
1034+ *pFormat = AUDIO_HW_IN_FORMAT;
1035+ return BAD_VALUE;
1036+ }
1037+ if (pRate == 0) {
1038+ return BAD_VALUE;
1039+ }
1040+ uint32_t rate = AudioHardware::getInputSampleRate(*pRate);
1041+ if (rate != *pRate) {
1042+ *pRate = rate;
1043+ return BAD_VALUE;
1044+ }
1045+
1046+ if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
1047+ *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
1048+ *pChannels = AUDIO_HW_IN_CHANNELS;
1049+ return BAD_VALUE;
1050+ }
1051+
1052+ mHardware = hw;
1053+
1054+ LOGV("AudioStreamInALSA::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
1055+
1056+ mBufferSize = getBufferSize(*pRate, AudioSystem::popCount(*pChannels));
1057+ mDevices = devices;
1058+ mChannels = *pChannels;
1059+ mChannelCount = AudioSystem::popCount(mChannels);
1060+ mSampleRate = rate;
1061+ if (mSampleRate != AUDIO_HW_OUT_SAMPLERATE) {
1062+ mDownSampler = new AudioHardware::DownSampler(mSampleRate,
1063+ mChannelCount,
1064+ AUDIO_HW_IN_PERIOD_SZ,
1065+ this);
1066+ status_t status = mDownSampler->initCheck();
1067+ if (status != NO_ERROR) {
1068+ delete mDownSampler;
1069+ LOGW("AudioStreamInALSA::set() downsampler init failed: %d", status);
1070+ return status;
1071+ }
1072+
1073+ mPcmIn = new int16_t[AUDIO_HW_IN_PERIOD_SZ * mChannelCount];
1074+ }
1075+ return NO_ERROR;
1076+}
1077+
1078+AudioHardware::AudioStreamInALSA::~AudioStreamInALSA()
1079+{
1080+ standby();
1081+ if (mDownSampler != NULL) {
1082+ delete mDownSampler;
1083+ if (mPcmIn != NULL) {
1084+ delete[] mPcmIn;
1085+ }
1086+ }
1087+}
1088+
1089+ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes)
1090+{
1091+ // LOGV("AudioStreamInALSA::read(%p, %u)", buffer, bytes);
1092+ status_t status = NO_INIT;
1093+ int ret;
1094+
1095+ if (mHardware == NULL) return NO_INIT;
1096+
1097+ { // scope for the lock
1098+ AutoMutex lock(mLock);
1099+
1100+ if (mStandby) {
1101+ AutoMutex hwLock(mHardware->lock());
1102+
1103+ LOGD("AudioHardware pcm capture is exiting standby.");
1104+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
1105+
1106+ sp<AudioStreamOutALSA> spOut = mHardware->output();
1107+ while (spOut != 0) {
1108+ if (!spOut->checkStandby()) {
1109+ int cnt = spOut->standbyCnt();
1110+ mHardware->lock().unlock();
1111+ mLock.unlock();
1112+ // Mutex acquisition order is always out -> in -> hw
1113+ spOut->lock();
1114+ mLock.lock();
1115+ mHardware->lock().lock();
1116+ // make sure that another thread did not change output state
1117+ // while the mutex is released
1118+ if ((spOut == mHardware->output()) && (cnt == spOut->standbyCnt())) {
1119+ LOGV("AudioStreamInALSA::read() force output standby");
1120+ spOut->close_l();
1121+ break;
1122+ }
1123+ spOut->unlock();
1124+ spOut = mHardware->output();
1125+ } else {
1126+ spOut.clear();
1127+ }
1128+ }
1129+ // spOut is not 0 here only if the output was active and has been
1130+ // closed above
1131+
1132+ // open output before input
1133+ if (spOut != 0) {
1134+ if (spOut->open_l() != NO_ERROR) {
1135+ spOut->doStandby_l();
1136+ }
1137+ spOut->unlock();
1138+ }
1139+
1140+ open_l();
1141+
1142+ if (mPcm == NULL) {
1143+ release_wake_lock("AudioInLock");
1144+ goto Error;
1145+ }
1146+ mStandby = false;
1147+ }
1148+
1149+
1150+ if (mDownSampler != NULL) {
1151+ size_t frames = bytes / frameSize();
1152+ size_t framesIn = 0;
1153+ mReadStatus = 0;
1154+ do {
1155+ size_t outframes = frames - framesIn;
1156+ mDownSampler->resample(
1157+ (int16_t *)buffer + (framesIn * mChannelCount),
1158+ &outframes);
1159+ framesIn += outframes;
1160+ } while ((framesIn < frames) && mReadStatus == 0);
1161+ ret = mReadStatus;
1162+ bytes = framesIn * frameSize();
1163+ } else {
1164+ TRACE_DRIVER_IN(DRV_PCM_READ)
1165+ ret = pcm_read(mPcm, buffer, bytes);
1166+ TRACE_DRIVER_OUT
1167+ }
1168+
1169+ if (ret == 0) {
1170+ return bytes;
1171+ }
1172+
1173+ LOGW("read error: %d", ret);
1174+ status = ret;
1175+ }
1176+
1177+Error:
1178+
1179+ standby();
1180+
1181+ // Simulate audio output timing in case of error
1182+ usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
1183+
1184+ return status;
1185+}
1186+
1187+status_t AudioHardware::AudioStreamInALSA::standby()
1188+{
1189+ if (mHardware == NULL) return NO_INIT;
1190+
1191+ AutoMutex lock(mLock);
1192+
1193+ { // scope for AudioHardware lock
1194+ AutoMutex hwLock(mHardware->lock());
1195+
1196+ doStandby_l();
1197+ }
1198+ return NO_ERROR;
1199+}
1200+
1201+void AudioHardware::AudioStreamInALSA::doStandby_l()
1202+{
1203+ mStandbyCnt++;
1204+
1205+ if (!mStandby) {
1206+ LOGD("AudioHardware pcm capture is going to standby.");
1207+ release_wake_lock("AudioInLock");
1208+ mStandby = true;
1209+ }
1210+ close_l();
1211+}
1212+
1213+void AudioHardware::AudioStreamInALSA::close_l()
1214+{
1215+ if (mMixer) {
1216+ mHardware->closeMixer_l();
1217+ mMixer = NULL;
1218+ mRouteCtl = NULL;
1219+ }
1220+
1221+ if (mPcm) {
1222+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
1223+ pcm_close(mPcm);
1224+ TRACE_DRIVER_OUT
1225+ mPcm = NULL;
1226+ }
1227+}
1228+
1229+status_t AudioHardware::AudioStreamInALSA::open_l()
1230+{
1231+ unsigned flags = PCM_IN;
1232+ if (mChannels == AudioSystem::CHANNEL_IN_MONO) {
1233+ flags |= PCM_MONO;
1234+ }
1235+ flags |= (AUDIO_HW_IN_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
1236+ flags |= (AUDIO_HW_IN_PERIOD_CNT - PCM_PERIOD_CNT_MIN)
1237+ << PCM_PERIOD_CNT_SHIFT;
1238+
1239+ LOGV("open pcm_in driver");
1240+ TRACE_DRIVER_IN(DRV_PCM_OPEN)
1241+ mPcm = pcm_open(flags);
1242+ TRACE_DRIVER_OUT
1243+ if (!pcm_ready(mPcm)) {
1244+ LOGE("cannot open pcm_in driver: %s\n", pcm_error(mPcm));
1245+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
1246+ pcm_close(mPcm);
1247+ TRACE_DRIVER_OUT
1248+ mPcm = NULL;
1249+ return NO_INIT;
1250+ }
1251+
1252+ if (mDownSampler != NULL) {
1253+ mInPcmInBuf = 0;
1254+ mDownSampler->reset();
1255+ }
1256+
1257+ mMixer = mHardware->openMixer_l();
1258+ if (mMixer) {
1259+ TRACE_DRIVER_IN(DRV_MIXER_GET)
1260+ mRouteCtl = mixer_get_control(mMixer, "Capture MIC Path", 0);
1261+ TRACE_DRIVER_OUT
1262+ }
1263+
1264+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
1265+ const char *route = mHardware->getInputRouteFromDevice(mDevices);
1266+ LOGV("read() wakeup setting route %s", route);
1267+ if (mRouteCtl) {
1268+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
1269+ mixer_ctl_select(mRouteCtl, route);
1270+ TRACE_DRIVER_OUT
1271+ }
1272+ }
1273+
1274+ return NO_ERROR;
1275+}
1276+
1277+status_t AudioHardware::AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
1278+{
1279+ const size_t SIZE = 256;
1280+ char buffer[SIZE];
1281+ String8 result;
1282+
1283+ bool locked = tryLock(mLock);
1284+ if (!locked) {
1285+ snprintf(buffer, SIZE, "\n\t\tAudioStreamInALSA maybe deadlocked\n");
1286+ } else {
1287+ mLock.unlock();
1288+ }
1289+
1290+ snprintf(buffer, SIZE, "\t\tmHardware: %p\n", mHardware);
1291+ result.append(buffer);
1292+ snprintf(buffer, SIZE, "\t\tmPcm: %p\n", mPcm);
1293+ result.append(buffer);
1294+ snprintf(buffer, SIZE, "\t\tmMixer: %p\n", mMixer);
1295+ result.append(buffer);
1296+ snprintf(buffer, SIZE, "\t\tStandby %s\n", (mStandby) ? "ON" : "OFF");
1297+ result.append(buffer);
1298+ snprintf(buffer, SIZE, "\t\tmDevices: 0x%08x\n", mDevices);
1299+ result.append(buffer);
1300+ snprintf(buffer, SIZE, "\t\tmChannels: 0x%08x\n", mChannels);
1301+ result.append(buffer);
1302+ snprintf(buffer, SIZE, "\t\tmSampleRate: %d\n", mSampleRate);
1303+ result.append(buffer);
1304+ snprintf(buffer, SIZE, "\t\tmBufferSize: %d\n", mBufferSize);
1305+ result.append(buffer);
1306+ snprintf(buffer, SIZE, "\t\tmDriverOp: %d\n", mDriverOp);
1307+ result.append(buffer);
1308+ write(fd, result.string(), result.size());
1309+
1310+ return NO_ERROR;
1311+}
1312+
1313+bool AudioHardware::AudioStreamInALSA::checkStandby()
1314+{
1315+ return mStandby;
1316+}
1317+
1318+status_t AudioHardware::AudioStreamInALSA::setParameters(const String8& keyValuePairs)
1319+{
1320+ AudioParameter param = AudioParameter(keyValuePairs);
1321+ status_t status = NO_ERROR;
1322+ int value;
1323+ String8 source;
1324+
1325+ LOGD("AudioStreamInALSA::setParameters() %s", keyValuePairs.string());
1326+
1327+ if (mHardware == NULL) return NO_INIT;
1328+
1329+ {
1330+ AutoMutex lock(mLock);
1331+
1332+ if (param.get(String8(INPUT_SOURCE_KEY), source) == NO_ERROR) {
1333+ AutoMutex hwLock(mHardware->lock());
1334+
1335+ mHardware->openMixer_l();
1336+ mHardware->setInputSource_l(source);
1337+ mHardware->closeMixer_l();
1338+
1339+ param.remove(String8(INPUT_SOURCE_KEY));
1340+ }
1341+
1342+ if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR)
1343+ {
1344+ if (value != 0) {
1345+ AutoMutex hwLock(mHardware->lock());
1346+
1347+ if (mDevices != (uint32_t)value) {
1348+ mDevices = (uint32_t)value;
1349+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
1350+ doStandby_l();
1351+ }
1352+ }
1353+ }
1354+ param.remove(String8(AudioParameter::keyRouting));
1355+ }
1356+ }
1357+
1358+
1359+ if (param.size()) {
1360+ status = BAD_VALUE;
1361+ }
1362+
1363+ return status;
1364+
1365+}
1366+
1367+String8 AudioHardware::AudioStreamInALSA::getParameters(const String8& keys)
1368+{
1369+ AudioParameter param = AudioParameter(keys);
1370+ String8 value;
1371+ String8 key = String8(AudioParameter::keyRouting);
1372+
1373+ if (param.get(key, value) == NO_ERROR) {
1374+ param.addInt(key, (int)mDevices);
1375+ }
1376+
1377+ LOGV("AudioStreamInALSA::getParameters() %s", param.toString().string());
1378+ return param.toString();
1379+}
1380+
1381+status_t AudioHardware::AudioStreamInALSA::getNextBuffer(AudioHardware::BufferProvider::Buffer* buffer)
1382+{
1383+ if (mPcm == NULL) {
1384+ buffer->raw = NULL;
1385+ buffer->frameCount = 0;
1386+ mReadStatus = NO_INIT;
1387+ return NO_INIT;
1388+ }
1389+
1390+ if (mInPcmInBuf == 0) {
1391+ TRACE_DRIVER_IN(DRV_PCM_READ)
1392+ mReadStatus = pcm_read(mPcm,(void*) mPcmIn, AUDIO_HW_IN_PERIOD_SZ * frameSize());
1393+ TRACE_DRIVER_OUT
1394+ if (mReadStatus != 0) {
1395+ buffer->raw = NULL;
1396+ buffer->frameCount = 0;
1397+ return mReadStatus;
1398+ }
1399+ mInPcmInBuf = AUDIO_HW_IN_PERIOD_SZ;
1400+ }
1401+
1402+ buffer->frameCount = (buffer->frameCount > mInPcmInBuf) ? mInPcmInBuf : buffer->frameCount;
1403+ buffer->i16 = mPcmIn + (AUDIO_HW_IN_PERIOD_SZ - mInPcmInBuf) * mChannelCount;
1404+
1405+ return mReadStatus;
1406+}
1407+
1408+void AudioHardware::AudioStreamInALSA::releaseBuffer(Buffer* buffer)
1409+{
1410+ mInPcmInBuf -= buffer->frameCount;
1411+}
1412+
1413+size_t AudioHardware::AudioStreamInALSA::getBufferSize(uint32_t sampleRate, int channelCount)
1414+{
1415+ size_t ratio;
1416+
1417+ switch (sampleRate) {
1418+ case 8000:
1419+ case 11025:
1420+ ratio = 4;
1421+ break;
1422+ case 16000:
1423+ case 22050:
1424+ ratio = 2;
1425+ break;
1426+ case 44100:
1427+ default:
1428+ ratio = 1;
1429+ break;
1430+ }
1431+
1432+ return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / ratio ;
1433+}
1434+
1435+//------------------------------------------------------------------------------
1436+// DownSampler
1437+//------------------------------------------------------------------------------
1438+
1439+/*
1440+ * 2.30 fixed point FIR filter coefficients for conversion 44100 -> 22050.
1441+ * (Works equivalently for 22010 -> 11025 or any other halving, of course.)
1442+ *
1443+ * Transition band from about 18 kHz, passband ripple < 0.1 dB,
1444+ * stopband ripple at about -55 dB, linear phase.
1445+ *
1446+ * Design and display in MATLAB or Octave using:
1447+ *
1448+ * filter = fir1(19, 0.5); filter = round(filter * 2**30); freqz(filter * 2**-30);
1449+ */
1450+static const int32_t filter_22khz_coeff[] = {
1451+ 2089257, 2898328, -5820678, -10484531,
1452+ 19038724, 30542725, -50469415, -81505260,
1453+ 152544464, 478517512, 478517512, 152544464,
1454+ -81505260, -50469415, 30542725, 19038724,
1455+ -10484531, -5820678, 2898328, 2089257,
1456+};
1457+#define NUM_COEFF_22KHZ (sizeof(filter_22khz_coeff) / sizeof(filter_22khz_coeff[0]))
1458+#define OVERLAP_22KHZ (NUM_COEFF_22KHZ - 2)
1459+
1460+/*
1461+ * Convolution of signals A and reverse(B). (In our case, the filter response
1462+ * is symmetric, so the reversing doesn't matter.)
1463+ * A is taken to be in 0.16 fixed-point, and B is taken to be in 2.30 fixed-point.
1464+ * The answer will be in 16.16 fixed-point, unclipped.
1465+ *
1466+ * This function would probably be the prime candidate for SIMD conversion if
1467+ * you want more speed.
1468+ */
1469+int32_t fir_convolve(const int16_t* a, const int32_t* b, int num_samples)
1470+{
1471+ int32_t sum = 1 << 13;
1472+ for (int i = 0; i < num_samples; ++i) {
1473+ sum += a[i] * (b[i] >> 16);
1474+ }
1475+ return sum >> 14;
1476+}
1477+
1478+/* Clip from 16.16 fixed-point to 0.16 fixed-point. */
1479+int16_t clip(int32_t x)
1480+{
1481+ if (x < -32768) {
1482+ return -32768;
1483+ } else if (x > 32767) {
1484+ return 32767;
1485+ } else {
1486+ return x;
1487+ }
1488+}
1489+
1490+/*
1491+ * Convert a chunk from 44 kHz to 22 kHz. Will update num_samples_in and num_samples_out
1492+ * accordingly, since it may leave input samples in the buffer due to overlap.
1493+ *
1494+ * Input and output are taken to be in 0.16 fixed-point.
1495+ */
1496+void resample_2_1(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
1497+{
1498+ if (*num_samples_in < (int)NUM_COEFF_22KHZ) {
1499+ *num_samples_out = 0;
1500+ return;
1501+ }
1502+
1503+ int odd_smp = *num_samples_in & 0x1;
1504+ int num_samples = *num_samples_in - odd_smp - OVERLAP_22KHZ;
1505+
1506+ for (int i = 0; i < num_samples; i += 2) {
1507+ output[i / 2] = clip(fir_convolve(input + i, filter_22khz_coeff, NUM_COEFF_22KHZ));
1508+ }
1509+
1510+ memmove(input, input + num_samples, (OVERLAP_22KHZ + odd_smp) * sizeof(*input));
1511+ *num_samples_out = num_samples / 2;
1512+ *num_samples_in = OVERLAP_22KHZ + odd_smp;
1513+}
1514+
1515+/*
1516+ * 2.30 fixed point FIR filter coefficients for conversion 22050 -> 16000,
1517+ * or 11025 -> 8000.
1518+ *
1519+ * Transition band from about 14 kHz, passband ripple < 0.1 dB,
1520+ * stopband ripple at about -50 dB, linear phase.
1521+ *
1522+ * Design and display in MATLAB or Octave using:
1523+ *
1524+ * filter = fir1(23, 16000 / 22050); filter = round(filter * 2**30); freqz(filter * 2**-30);
1525+ */
1526+static const int32_t filter_16khz_coeff[] = {
1527+ 2057290, -2973608, 1880478, 4362037,
1528+ -14639744, 18523609, -1609189, -38502470,
1529+ 78073125, -68353935, -59103896, 617555440,
1530+ 617555440, -59103896, -68353935, 78073125,
1531+ -38502470, -1609189, 18523609, -14639744,
1532+ 4362037, 1880478, -2973608, 2057290,
1533+};
1534+#define NUM_COEFF_16KHZ (sizeof(filter_16khz_coeff) / sizeof(filter_16khz_coeff[0]))
1535+#define OVERLAP_16KHZ (NUM_COEFF_16KHZ - 1)
1536+
1537+/*
1538+ * Convert a chunk from 22 kHz to 16 kHz. Will update num_samples_in and
1539+ * num_samples_out accordingly, since it may leave input samples in the buffer
1540+ * due to overlap.
1541+ *
1542+ * This implementation is rather ad-hoc; it first low-pass filters the data
1543+ * into a temporary buffer, and then converts chunks of 441 input samples at a
1544+ * time into 320 output samples by simple linear interpolation. A better
1545+ * implementation would use a polyphase filter bank to do these two operations
1546+ * in one step.
1547+ *
1548+ * Input and output are taken to be in 0.16 fixed-point.
1549+ */
1550+
1551+#define RESAMPLE_16KHZ_SAMPLES_IN 441
1552+#define RESAMPLE_16KHZ_SAMPLES_OUT 320
1553+
1554+void resample_441_320(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
1555+{
1556+ const int num_blocks = (*num_samples_in - OVERLAP_16KHZ) / RESAMPLE_16KHZ_SAMPLES_IN;
1557+ if (num_blocks < 1) {
1558+ *num_samples_out = 0;
1559+ return;
1560+ }
1561+
1562+ for (int i = 0; i < num_blocks; ++i) {
1563+ uint32_t tmp[RESAMPLE_16KHZ_SAMPLES_IN];
1564+ for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_IN; ++j) {
1565+ tmp[j] = fir_convolve(input + i * RESAMPLE_16KHZ_SAMPLES_IN + j,
1566+ filter_16khz_coeff,
1567+ NUM_COEFF_16KHZ);
1568+ }
1569+
1570+ const float step_float = (float)RESAMPLE_16KHZ_SAMPLES_IN / (float)RESAMPLE_16KHZ_SAMPLES_OUT;
1571+
1572+ uint32_t in_sample_num = 0; // 16.16 fixed point
1573+ const uint32_t step = (uint32_t)(step_float * 65536.0f + 0.5f); // 16.16 fixed point
1574+ for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_OUT; ++j, in_sample_num += step) {
1575+ const uint32_t whole = in_sample_num >> 16;
1576+ const uint32_t frac = (in_sample_num & 0xffff); // 0.16 fixed point
1577+ const int32_t s1 = tmp[whole];
1578+ const int32_t s2 = tmp[whole + 1];
1579+ *output++ = clip(s1 + (((s2 - s1) * (int32_t)frac) >> 16));
1580+ }
1581+ }
1582+
1583+ const int samples_consumed = num_blocks * RESAMPLE_16KHZ_SAMPLES_IN;
1584+ memmove(input, input + samples_consumed, (*num_samples_in - samples_consumed) * sizeof(*input));
1585+ *num_samples_in -= samples_consumed;
1586+ *num_samples_out = RESAMPLE_16KHZ_SAMPLES_OUT * num_blocks;
1587+}
1588+
1589+
1590+AudioHardware::DownSampler::DownSampler(uint32_t outSampleRate,
1591+ uint32_t channelCount,
1592+ uint32_t frameCount,
1593+ AudioHardware::BufferProvider* provider)
1594+ : mStatus(NO_INIT), mProvider(provider), mSampleRate(outSampleRate),
1595+ mChannelCount(channelCount), mFrameCount(frameCount),
1596+ mInLeft(NULL), mInRight(NULL), mTmpLeft(NULL), mTmpRight(NULL),
1597+ mTmp2Left(NULL), mTmp2Right(NULL), mOutLeft(NULL), mOutRight(NULL)
1598+
1599+{
1600+ LOGV("AudioHardware::DownSampler() cstor %p SR %d channels %d frames %d",
1601+ this, mSampleRate, mChannelCount, mFrameCount);
1602+
1603+ if (mSampleRate != 8000 && mSampleRate != 11025 && mSampleRate != 16000 &&
1604+ mSampleRate != 22050) {
1605+ LOGW("AudioHardware::DownSampler cstor: bad sampling rate: %d", mSampleRate);
1606+ return;
1607+ }
1608+
1609+ mInLeft = new int16_t[mFrameCount];
1610+ mInRight = new int16_t[mFrameCount];
1611+ mTmpLeft = new int16_t[mFrameCount];
1612+ mTmpRight = new int16_t[mFrameCount];
1613+ mTmp2Left = new int16_t[mFrameCount];
1614+ mTmp2Right = new int16_t[mFrameCount];
1615+ mOutLeft = new int16_t[mFrameCount];
1616+ mOutRight = new int16_t[mFrameCount];
1617+
1618+ mStatus = NO_ERROR;
1619+}
1620+
1621+AudioHardware::DownSampler::~DownSampler()
1622+{
1623+ if (mInLeft) delete[] mInLeft;
1624+ if (mInRight) delete[] mInRight;
1625+ if (mTmpLeft) delete[] mTmpLeft;
1626+ if (mTmpRight) delete[] mTmpRight;
1627+ if (mTmp2Left) delete[] mTmp2Left;
1628+ if (mTmp2Right) delete[] mTmp2Right;
1629+ if (mOutLeft) delete[] mOutLeft;
1630+ if (mOutRight) delete[] mOutRight;
1631+}
1632+
1633+void AudioHardware::DownSampler::reset()
1634+{
1635+ mInInBuf = 0;
1636+ mInTmpBuf = 0;
1637+ mInTmp2Buf = 0;
1638+ mOutBufPos = 0;
1639+ mInOutBuf = 0;
1640+}
1641+
1642+
1643+int AudioHardware::DownSampler::resample(int16_t* out, size_t *outFrameCount)
1644+{
1645+ if (mStatus != NO_ERROR) {
1646+ return mStatus;
1647+ }
1648+
1649+ if (out == NULL || outFrameCount == NULL) {
1650+ return BAD_VALUE;
1651+ }
1652+
1653+ int16_t *outLeft = mTmp2Left;
1654+ int16_t *outRight = mTmp2Left;
1655+ if (mSampleRate == 22050) {
1656+ outLeft = mTmpLeft;
1657+ outRight = mTmpRight;
1658+ } else if (mSampleRate == 8000){
1659+ outLeft = mOutLeft;
1660+ outRight = mOutRight;
1661+ }
1662+
1663+ int outFrames = 0;
1664+ int remaingFrames = *outFrameCount;
1665+
1666+ if (mInOutBuf) {
1667+ int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
1668+
1669+ for (int i = 0; i < frames; ++i) {
1670+ out[i] = outLeft[mOutBufPos + i];
1671+ }
1672+ if (mChannelCount == 2) {
1673+ for (int i = 0; i < frames; ++i) {
1674+ out[i * 2] = outLeft[mOutBufPos + i];
1675+ out[i * 2 + 1] = outRight[mOutBufPos + i];
1676+ }
1677+ }
1678+ remaingFrames -= frames;
1679+ mInOutBuf -= frames;
1680+ mOutBufPos += frames;
1681+ outFrames += frames;
1682+ }
1683+
1684+ while (remaingFrames) {
1685+ LOGW_IF((mInOutBuf != 0), "mInOutBuf should be 0 here");
1686+
1687+ AudioHardware::BufferProvider::Buffer buf;
1688+ buf.frameCount = mFrameCount - mInInBuf;
1689+ int ret = mProvider->getNextBuffer(&buf);
1690+ if (buf.raw == NULL) {
1691+ *outFrameCount = outFrames;
1692+ return ret;
1693+ }
1694+
1695+ for (size_t i = 0; i < buf.frameCount; ++i) {
1696+ mInLeft[i + mInInBuf] = buf.i16[i];
1697+ }
1698+ if (mChannelCount == 2) {
1699+ for (size_t i = 0; i < buf.frameCount; ++i) {
1700+ mInLeft[i + mInInBuf] = buf.i16[i * 2];
1701+ mInRight[i + mInInBuf] = buf.i16[i * 2 + 1];
1702+ }
1703+ }
1704+ mInInBuf += buf.frameCount;
1705+ mProvider->releaseBuffer(&buf);
1706+
1707+ /* 44010 -> 22050 */
1708+ {
1709+ int samples_in_left = mInInBuf;
1710+ int samples_out_left;
1711+ resample_2_1(mInLeft, mTmpLeft + mInTmpBuf, &samples_in_left, &samples_out_left);
1712+
1713+ if (mChannelCount == 2) {
1714+ int samples_in_right = mInInBuf;
1715+ int samples_out_right;
1716+ resample_2_1(mInRight, mTmpRight + mInTmpBuf, &samples_in_right, &samples_out_right);
1717+ }
1718+
1719+ mInInBuf = samples_in_left;
1720+ mInTmpBuf += samples_out_left;
1721+ mInOutBuf = samples_out_left;
1722+ }
1723+
1724+ if (mSampleRate == 11025 || mSampleRate == 8000) {
1725+ /* 22050 - > 11025 */
1726+ int samples_in_left = mInTmpBuf;
1727+ int samples_out_left;
1728+ resample_2_1(mTmpLeft, mTmp2Left + mInTmp2Buf, &samples_in_left, &samples_out_left);
1729+
1730+ if (mChannelCount == 2) {
1731+ int samples_in_right = mInTmpBuf;
1732+ int samples_out_right;
1733+ resample_2_1(mTmpRight, mTmp2Right + mInTmp2Buf, &samples_in_right, &samples_out_right);
1734+ }
1735+
1736+
1737+ mInTmpBuf = samples_in_left;
1738+ mInTmp2Buf += samples_out_left;
1739+ mInOutBuf = samples_out_left;
1740+
1741+ if (mSampleRate == 8000) {
1742+ /* 11025 -> 8000*/
1743+ int samples_in_left = mInTmp2Buf;
1744+ int samples_out_left;
1745+ resample_441_320(mTmp2Left, mOutLeft, &samples_in_left, &samples_out_left);
1746+
1747+ if (mChannelCount == 2) {
1748+ int samples_in_right = mInTmp2Buf;
1749+ int samples_out_right;
1750+ resample_441_320(mTmp2Right, mOutRight, &samples_in_right, &samples_out_right);
1751+ }
1752+
1753+ mInTmp2Buf = samples_in_left;
1754+ mInOutBuf = samples_out_left;
1755+ } else {
1756+ mInTmp2Buf = 0;
1757+ }
1758+
1759+ } else if (mSampleRate == 16000) {
1760+ /* 22050 -> 16000*/
1761+ int samples_in_left = mInTmpBuf;
1762+ int samples_out_left;
1763+ resample_441_320(mTmpLeft, mTmp2Left, &samples_in_left, &samples_out_left);
1764+
1765+ if (mChannelCount == 2) {
1766+ int samples_in_right = mInTmpBuf;
1767+ int samples_out_right;
1768+ resample_441_320(mTmpRight, mTmp2Right, &samples_in_right, &samples_out_right);
1769+ }
1770+
1771+ mInTmpBuf = samples_in_left;
1772+ mInOutBuf = samples_out_left;
1773+ } else {
1774+ mInTmpBuf = 0;
1775+ }
1776+
1777+ int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
1778+
1779+ for (int i = 0; i < frames; ++i) {
1780+ out[outFrames + i] = outLeft[i];
1781+ }
1782+ if (mChannelCount == 2) {
1783+ for (int i = 0; i < frames; ++i) {
1784+ out[(outFrames + i) * 2] = outLeft[i];
1785+ out[(outFrames + i) * 2 + 1] = outRight[i];
1786+ }
1787+ }
1788+ remaingFrames -= frames;
1789+ outFrames += frames;
1790+ mOutBufPos = frames;
1791+ mInOutBuf -= frames;
1792+ }
1793+
1794+ return 0;
1795+}
1796+
1797+
1798+
1799+
1800+
1801+
1802+
1803+//------------------------------------------------------------------------------
1804+// Factory
1805+//------------------------------------------------------------------------------
1806+
1807+extern "C" AudioHardwareInterface* createAudioHardware(void) {
1808+ return new AudioHardware();
1809+}
1810+
1811+}; // namespace android
--- /dev/null
+++ b/AudioHardware.h
@@ -0,0 +1,331 @@
1+/*
2+** Copyright 2011, The Android Open-Source Project
3+**
4+** Licensed under the Apache License, Version 2.0 (the "License");
5+** you may not use this file except in compliance with the License.
6+** You may obtain a copy of the License at
7+**
8+** http://www.apache.org/licenses/LICENSE-2.0
9+**
10+** Unless required by applicable law or agreed to in writing, software
11+** distributed under the License is distributed on an "AS IS" BASIS,
12+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+** See the License for the specific language governing permissions and
14+** limitations under the License.
15+*/
16+
17+#ifndef ANDROID_AUDIO_HARDWARE_H
18+#define ANDROID_AUDIO_HARDWARE_H
19+
20+#include <stdint.h>
21+#include <sys/types.h>
22+
23+#include <utils/threads.h>
24+#include <utils/SortedVector.h>
25+
26+#include <hardware_legacy/AudioHardwareBase.h>
27+
28+extern "C" {
29+ struct pcm;
30+ struct mixer;
31+ struct mixer_ctl;
32+};
33+
34+namespace android_audio_legacy {
35+
36+using android::sp;
37+using android::Mutex;
38+using android::AutoMutex;
39+using android::SortedVector;
40+using android::RefBase;
41+
42+// TODO: determine actual audio DSP and hardware latency
43+// Additionnal latency introduced by audio DSP and hardware in ms
44+#define AUDIO_HW_OUT_LATENCY_MS 0
45+// Default audio output sample rate
46+#define AUDIO_HW_OUT_SAMPLERATE 44100
47+// Default audio output channel mask
48+#define AUDIO_HW_OUT_CHANNELS (AudioSystem::CHANNEL_OUT_STEREO)
49+// Default audio output sample format
50+#define AUDIO_HW_OUT_FORMAT (AudioSystem::PCM_16_BIT)
51+// Kernel pcm out buffer size in frames at 44.1kHz
52+#define AUDIO_HW_OUT_PERIOD_MULT 8 // (8 * 128 = 1024 frames)
53+#define AUDIO_HW_OUT_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_OUT_PERIOD_MULT)
54+#define AUDIO_HW_OUT_PERIOD_CNT 4
55+// Default audio output buffer size in bytes
56+#define AUDIO_HW_OUT_PERIOD_BYTES (AUDIO_HW_OUT_PERIOD_SZ * 2 * sizeof(int16_t))
57+
58+// Default audio input sample rate
59+#define AUDIO_HW_IN_SAMPLERATE 8000
60+// Default audio input channel mask
61+#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO)
62+// Default audio input sample format
63+#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT)
64+// Number of buffers in audio driver for input
65+#define AUDIO_HW_NUM_IN_BUF 2
66+// Kernel pcm in buffer size in frames at 44.1kHz (before resampling)
67+#define AUDIO_HW_IN_PERIOD_MULT 16 // (16 * 128 = 2048 frames)
68+#define AUDIO_HW_IN_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_IN_PERIOD_MULT)
69+#define AUDIO_HW_IN_PERIOD_CNT 2
70+// Default audio input buffer size in bytes (8kHz mono)
71+#define AUDIO_HW_IN_PERIOD_BYTES ((AUDIO_HW_IN_PERIOD_SZ*sizeof(int16_t))/8)
72+
73+#define INPUT_SOURCE_KEY "Input Source"
74+
75+class AudioHardware : public AudioHardwareBase {
76+ class AudioStreamOutALSA;
77+ class AudioStreamInALSA;
78+
79+public:
80+
81+ AudioHardware();
82+ virtual ~AudioHardware();
83+ virtual status_t initCheck();
84+
85+ virtual status_t setVoiceVolume(float volume);
86+ virtual status_t setMasterVolume(float volume);
87+
88+ virtual status_t setMode(int mode);
89+
90+ virtual status_t setMicMute(bool state);
91+ virtual status_t getMicMute(bool* state);
92+
93+ virtual status_t setParameters(const String8& keyValuePairs);
94+ virtual String8 getParameters(const String8& keys);
95+
96+ virtual AudioStreamOut* openOutputStream(
97+ uint32_t devices, int *format=0, uint32_t *channels=0,
98+ uint32_t *sampleRate=0, status_t *status=0);
99+
100+ virtual AudioStreamIn* openInputStream(
101+ uint32_t devices, int *format, uint32_t *channels,
102+ uint32_t *sampleRate, status_t *status,
103+ AudioSystem::audio_in_acoustics acoustics);
104+
105+ virtual void closeOutputStream(AudioStreamOut* out);
106+ virtual void closeInputStream(AudioStreamIn* in);
107+
108+ virtual size_t getInputBufferSize(
109+ uint32_t sampleRate, int format, int channelCount);
110+
111+ int mode() { return mMode; }
112+ const char *getOutputRouteFromDevice(uint32_t device);
113+ const char *getInputRouteFromDevice(uint32_t device);
114+ const char *getVoiceRouteFromDevice(uint32_t device);
115+
116+ status_t setIncallPath_l(uint32_t device);
117+
118+ status_t setInputSource_l(String8 source);
119+
120+ static uint32_t getInputSampleRate(uint32_t sampleRate);
121+ sp <AudioStreamInALSA> getActiveInput_l();
122+
123+ Mutex& lock() { return mLock; }
124+
125+ struct pcm *openPcmOut_l();
126+ void closePcmOut_l();
127+
128+ struct mixer *openMixer_l();
129+ void closeMixer_l();
130+
131+ sp <AudioStreamOutALSA> output() { return mOutput; }
132+
133+protected:
134+ virtual status_t dump(int fd, const Vector<String16>& args);
135+
136+private:
137+
138+ bool mInit;
139+ bool mMicMute;
140+ sp <AudioStreamOutALSA> mOutput;
141+ SortedVector < sp<AudioStreamInALSA> > mInputs;
142+ Mutex mLock;
143+ struct pcm* mPcm;
144+ struct mixer* mMixer;
145+ uint32_t mPcmOpenCnt;
146+ uint32_t mMixerOpenCnt;
147+ bool mInCallAudioMode;
148+
149+ String8 mInputSource;
150+ bool mBluetoothNrec;
151+ bool mActivatedCP;
152+ // trace driver operations for dump
153+ int mDriverOp;
154+
155+ static uint32_t checkInputSampleRate(uint32_t sampleRate);
156+ static const uint32_t inputSamplingRates[];
157+
158+ class AudioStreamOutALSA : public AudioStreamOut, public RefBase {
159+ public:
160+ AudioStreamOutALSA();
161+ virtual ~AudioStreamOutALSA();
162+ status_t set(AudioHardware* mHardware,
163+ uint32_t devices,
164+ int *pFormat,
165+ uint32_t *pChannels,
166+ uint32_t *pRate);
167+ virtual uint32_t sampleRate() const { return mSampleRate; }
168+ virtual size_t bufferSize() const { return mBufferSize; }
169+ virtual uint32_t channels() const { return mChannels; }
170+ virtual int format() const { return AUDIO_HW_OUT_FORMAT; }
171+ virtual uint32_t latency() const
172+ {
173+ return (1000 * AUDIO_HW_OUT_PERIOD_CNT *
174+ (bufferSize()/frameSize()))/sampleRate() + AUDIO_HW_OUT_LATENCY_MS;
175+ }
176+ virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
177+ virtual ssize_t write(const void* buffer, size_t bytes);
178+ virtual status_t standby();
179+ bool checkStandby();
180+
181+ virtual status_t dump(int fd, const Vector<String16>& args);
182+ virtual status_t setParameters(const String8& keyValuePairs);
183+ virtual String8 getParameters(const String8& keys);
184+ uint32_t device() { return mDevices; }
185+ virtual status_t getRenderPosition(uint32_t *dspFrames);
186+
187+ void doStandby_l();
188+ void close_l();
189+ status_t open_l();
190+ int standbyCnt() { return mStandbyCnt; }
191+
192+ void lock() { mLock.lock(); }
193+ void unlock() { mLock.unlock(); }
194+
195+ private:
196+ Mutex mLock;
197+ AudioHardware *mHardware;
198+ struct pcm *mPcm;
199+ struct mixer *mMixer;
200+ struct mixer_ctl *mRouteCtl;
201+ const char *next_route;
202+ bool mStandby;
203+ uint32_t mDevices;
204+ uint32_t mChannels;
205+ uint32_t mSampleRate;
206+ size_t mBufferSize;
207+ // trace driver operations for dump
208+ int mDriverOp;
209+ int mStandbyCnt;
210+ };
211+
212+ class BufferProvider {
213+ public:
214+
215+ struct Buffer {
216+ union {
217+ void* raw;
218+ short* i16;
219+ int8_t* i8;
220+ };
221+ size_t frameCount;
222+ };
223+
224+ virtual ~BufferProvider() {}
225+
226+ virtual status_t getNextBuffer(Buffer* buffer) = 0;
227+ virtual void releaseBuffer(Buffer* buffer) = 0;
228+ };
229+
230+ class DownSampler {
231+ public:
232+ DownSampler(uint32_t outSampleRate,
233+ uint32_t channelCount,
234+ uint32_t frameCount,
235+ BufferProvider *provider);
236+
237+ virtual ~DownSampler();
238+
239+ void reset();
240+ status_t initCheck() { return mStatus; }
241+ int resample(int16_t *out, size_t *outFrameCount);
242+
243+ private:
244+ status_t mStatus;
245+ BufferProvider *mProvider;
246+ uint32_t mSampleRate;
247+ uint32_t mChannelCount;
248+ uint32_t mFrameCount;
249+ int16_t *mInLeft;
250+ int16_t *mInRight;
251+ int16_t *mTmpLeft;
252+ int16_t *mTmpRight;
253+ int16_t *mTmp2Left;
254+ int16_t *mTmp2Right;
255+ int16_t *mOutLeft;
256+ int16_t *mOutRight;
257+ int mInInBuf;
258+ int mInTmpBuf;
259+ int mInTmp2Buf;
260+ int mOutBufPos;
261+ int mInOutBuf;
262+ };
263+
264+
265+ class AudioStreamInALSA : public AudioStreamIn, public BufferProvider, public RefBase {
266+ public:
267+ AudioStreamInALSA();
268+ virtual ~AudioStreamInALSA();
269+ status_t set(AudioHardware* hw,
270+ uint32_t devices,
271+ int *pFormat,
272+ uint32_t *pChannels,
273+ uint32_t *pRate,
274+ AudioSystem::audio_in_acoustics acoustics);
275+ virtual size_t bufferSize() const { return mBufferSize; }
276+ virtual uint32_t channels() const { return mChannels; }
277+ virtual int format() const { return AUDIO_HW_IN_FORMAT; }
278+ virtual uint32_t sampleRate() const { return mSampleRate; }
279+ virtual status_t setGain(float gain) { return INVALID_OPERATION; }
280+ virtual ssize_t read(void* buffer, ssize_t bytes);
281+ virtual status_t dump(int fd, const Vector<String16>& args);
282+ virtual status_t standby();
283+ virtual status_t setParameters(const String8& keyValuePairs);
284+ virtual String8 getParameters(const String8& keys);
285+ virtual unsigned int getInputFramesLost() const { return 0; }
286+ virtual status_t addAudioEffect(effect_handle_t effect) { return NO_ERROR; }
287+ virtual status_t removeAudioEffect(effect_handle_t effect) { return NO_ERROR; }
288+
289+ bool checkStandby();
290+ uint32_t device() { return mDevices; }
291+ void doStandby_l();
292+ void close_l();
293+ status_t open_l();
294+ int standbyCnt() { return mStandbyCnt; }
295+
296+ static size_t getBufferSize(uint32_t sampleRate, int channelCount);
297+
298+ // BufferProvider
299+ virtual status_t getNextBuffer(BufferProvider::Buffer* buffer);
300+ virtual void releaseBuffer(BufferProvider::Buffer* buffer);
301+
302+ void lock() { mLock.lock(); }
303+ void unlock() { mLock.unlock(); }
304+
305+ private:
306+ Mutex mLock;
307+ AudioHardware *mHardware;
308+ struct pcm *mPcm;
309+ struct mixer *mMixer;
310+ struct mixer_ctl *mRouteCtl;
311+ const char *next_route;
312+ bool mStandby;
313+ uint32_t mDevices;
314+ uint32_t mChannels;
315+ uint32_t mChannelCount;
316+ uint32_t mSampleRate;
317+ size_t mBufferSize;
318+ DownSampler *mDownSampler;
319+ status_t mReadStatus;
320+ size_t mInPcmInBuf;
321+ int16_t *mPcmIn;
322+ // trace driver operations for dump
323+ int mDriverOp;
324+ int mStandbyCnt;
325+ };
326+
327+};
328+
329+}; // namespace android
330+
331+#endif
--- /dev/null
+++ b/alsa.mk
@@ -0,0 +1,53 @@
1+#
2+# Copyright (C) 2011 The Android-x86 Open Source Project
3+#
4+# Licensed under the Apache License, Version 2.0 (the "License");
5+# you may not use this file except in compliance with the License.
6+# You may obtain a copy of the License at
7+#
8+# http://www.apache.org/licenses/LICENSE-2.0
9+#
10+
11+TARGET_ALSA_CONF_DIR := system/usr/share/alsa
12+LOCAL_ALSA_CONF_DIR := external/alsa-lib/src/conf
13+
14+copy_conf := \
15+ alsa.conf \
16+ pcm/dsnoop.conf \
17+ pcm/modem.conf \
18+ pcm/dpl.conf \
19+ pcm/default.conf \
20+ pcm/surround51.conf \
21+ pcm/surround41.conf \
22+ pcm/surround50.conf \
23+ pcm/dmix.conf \
24+ pcm/center_lfe.conf \
25+ pcm/surround40.conf \
26+ pcm/side.conf \
27+ pcm/iec958.conf \
28+ pcm/rear.conf \
29+ pcm/surround71.conf \
30+ pcm/front.conf \
31+ cards/aliases.conf
32+
33+LOCAL_ALSA_INIT_DIR := external/alsa-utils/alsactl/init
34+
35+copy_init := \
36+ 00main \
37+ default \
38+ hda \
39+ help \
40+ info \
41+ test
42+
43+PRODUCT_COPY_FILES := \
44+ $(foreach f,$(copy_conf),$(LOCAL_ALSA_CONF_DIR)/$(f):$(TARGET_ALSA_CONF_DIR)/$(f)) \
45+ $(foreach f,$(copy_init),$(LOCAL_ALSA_INIT_DIR)/$(f):$(TARGET_ALSA_CONF_DIR)/init/$(f))
46+
47+PRODUCT_PACKAGES := \
48+ audio.primary.$(TARGET_PRODUCT) \
49+ audio_policy.$(TARGET_PRODUCT) \
50+ audio.primary.default \
51+ audio.a2dp.default \
52+ audio_policy.default \
53+ alsa_ctl \
--- /dev/null
+++ b/alsa_audio.h
@@ -0,0 +1,85 @@
1+/*
2+** Copyright 2010, The Android Open-Source Project
3+**
4+** Licensed under the Apache License, Version 2.0 (the "License");
5+** you may not use this file except in compliance with the License.
6+** You may obtain a copy of the License at
7+**
8+** http://www.apache.org/licenses/LICENSE-2.0
9+**
10+** Unless required by applicable law or agreed to in writing, software
11+** distributed under the License is distributed on an "AS IS" BASIS,
12+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+** See the License for the specific language governing permissions and
14+** limitations under the License.
15+*/
16+
17+#ifndef _AUDIO_H_
18+#define _AUDIO_H_
19+
20+#if defined(__cplusplus)
21+extern "C" {
22+#endif
23+
24+struct pcm;
25+
26+#define PCM_OUT 0x00000000
27+#define PCM_IN 0x10000000
28+
29+#define PCM_STEREO 0x00000000
30+#define PCM_MONO 0x01000000
31+
32+#define PCM_44100HZ 0x00000000
33+#define PCM_48000HZ 0x00100000
34+#define PCM_8000HZ 0x00200000
35+#define PCM_RATE_MASK 0x00F00000
36+
37+#define PCM_PERIOD_CNT_MIN 2
38+#define PCM_PERIOD_CNT_SHIFT 16
39+#define PCM_PERIOD_CNT_MASK (0xF << PCM_PERIOD_CNT_SHIFT)
40+#define PCM_PERIOD_SZ_MIN 128
41+#define PCM_PERIOD_SZ_SHIFT 12
42+#define PCM_PERIOD_SZ_MASK (0xF << PCM_PERIOD_SZ_SHIFT)
43+
44+/* Acquire/release a pcm channel.
45+ * Returns non-zero on error
46+ */
47+struct pcm *pcm_open(unsigned flags);
48+int pcm_close(struct pcm *pcm);
49+int pcm_ready(struct pcm *pcm);
50+
51+/* Returns a human readable reason for the last error. */
52+const char *pcm_error(struct pcm *pcm);
53+
54+/* Returns the buffer size (int bytes) that should be used for pcm_write.
55+ * This will be 1/2 of the actual fifo size.
56+ */
57+unsigned pcm_buffer_size(struct pcm *pcm);
58+
59+/* Write data to the fifo.
60+ * Will start playback on the first write or on a write that
61+ * occurs after a fifo underrun.
62+ */
63+int pcm_write(struct pcm *pcm, void *data, unsigned count);
64+int pcm_read(struct pcm *pcm, void *data, unsigned count);
65+
66+struct mixer;
67+struct mixer_ctl;
68+
69+struct mixer *mixer_open(void);
70+void mixer_close(struct mixer *mixer);
71+void mixer_dump(struct mixer *mixer);
72+
73+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
74+ const char *name, unsigned index);
75+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n);
76+
77+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent);
78+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value);
79+void mixer_ctl_print(struct mixer_ctl *ctl);
80+
81+#if defined(__cplusplus)
82+} /* extern "C" */
83+#endif
84+
85+#endif
--- /dev/null
+++ b/alsa_mixer.c
@@ -0,0 +1,371 @@
1+/*
2+** Copyright 2010, The Android Open-Source Project
3+**
4+** Licensed under the Apache License, Version 2.0 (the "License");
5+** you may not use this file except in compliance with the License.
6+** You may obtain a copy of the License at
7+**
8+** http://www.apache.org/licenses/LICENSE-2.0
9+**
10+** Unless required by applicable law or agreed to in writing, software
11+** distributed under the License is distributed on an "AS IS" BASIS,
12+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+** See the License for the specific language governing permissions and
14+** limitations under the License.
15+*/
16+
17+#include <stdio.h>
18+#include <stdlib.h>
19+#include <string.h>
20+#include <unistd.h>
21+#include <fcntl.h>
22+#include <errno.h>
23+#include <ctype.h>
24+
25+#include <linux/ioctl.h>
26+#define __force
27+#define __bitwise
28+#define __user
29+#include "asound.h"
30+
31+#include "alsa_audio.h"
32+
33+static const char *elem_iface_name(snd_ctl_elem_iface_t n)
34+{
35+ switch (n) {
36+ case SNDRV_CTL_ELEM_IFACE_CARD: return "CARD";
37+ case SNDRV_CTL_ELEM_IFACE_HWDEP: return "HWDEP";
38+ case SNDRV_CTL_ELEM_IFACE_MIXER: return "MIXER";
39+ case SNDRV_CTL_ELEM_IFACE_PCM: return "PCM";
40+ case SNDRV_CTL_ELEM_IFACE_RAWMIDI: return "MIDI";
41+ case SNDRV_CTL_ELEM_IFACE_TIMER: return "TIMER";
42+ case SNDRV_CTL_ELEM_IFACE_SEQUENCER: return "SEQ";
43+ default: return "???";
44+ }
45+}
46+
47+static const char *elem_type_name(snd_ctl_elem_type_t n)
48+{
49+ switch (n) {
50+ case SNDRV_CTL_ELEM_TYPE_NONE: return "NONE";
51+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
52+ case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT32";
53+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
54+ case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTES";
55+ case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
56+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
57+ default: return "???";
58+ }
59+}
60+
61+
62+struct mixer_ctl {
63+ struct mixer *mixer;
64+ struct snd_ctl_elem_info *info;
65+ char **ename;
66+};
67+
68+struct mixer {
69+ int fd;
70+ struct snd_ctl_elem_info *info;
71+ struct mixer_ctl *ctl;
72+ unsigned count;
73+};
74+
75+void mixer_close(struct mixer *mixer)
76+{
77+ unsigned n,m;
78+
79+ if (mixer->fd >= 0)
80+ close(mixer->fd);
81+
82+ if (mixer->ctl) {
83+ for (n = 0; n < mixer->count; n++) {
84+ if (mixer->ctl[n].ename) {
85+ unsigned max = mixer->ctl[n].info->value.enumerated.items;
86+ for (m = 0; m < max; m++)
87+ free(mixer->ctl[n].ename[m]);
88+ free(mixer->ctl[n].ename);
89+ }
90+ }
91+ free(mixer->ctl);
92+ }
93+
94+ if (mixer->info)
95+ free(mixer->info);
96+
97+ free(mixer);
98+}
99+
100+struct mixer *mixer_open(void)
101+{
102+ struct snd_ctl_elem_list elist;
103+ struct snd_ctl_elem_info tmp;
104+ struct snd_ctl_elem_id *eid = NULL;
105+ struct mixer *mixer = NULL;
106+ unsigned n, m;
107+ int fd;
108+
109+ fd = open("/dev/snd/controlC0", O_RDWR);
110+ if (fd < 0)
111+ return 0;
112+
113+ memset(&elist, 0, sizeof(elist));
114+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
115+ goto fail;
116+
117+ mixer = calloc(1, sizeof(*mixer));
118+ if (!mixer)
119+ goto fail;
120+
121+ mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
122+ mixer->info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
123+ if (!mixer->ctl || !mixer->info)
124+ goto fail;
125+
126+ eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
127+ if (!eid)
128+ goto fail;
129+
130+ mixer->count = elist.count;
131+ mixer->fd = fd;
132+ elist.space = mixer->count;
133+ elist.pids = eid;
134+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
135+ goto fail;
136+
137+ for (n = 0; n < mixer->count; n++) {
138+ struct snd_ctl_elem_info *ei = mixer->info + n;
139+ ei->id.numid = eid[n].numid;
140+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
141+ goto fail;
142+ mixer->ctl[n].info = ei;
143+ mixer->ctl[n].mixer = mixer;
144+ if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
145+ char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
146+ if (!enames)
147+ goto fail;
148+ mixer->ctl[n].ename = enames;
149+ for (m = 0; m < ei->value.enumerated.items; m++) {
150+ memset(&tmp, 0, sizeof(tmp));
151+ tmp.id.numid = ei->id.numid;
152+ tmp.value.enumerated.item = m;
153+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
154+ goto fail;
155+ enames[m] = strdup(tmp.value.enumerated.name);
156+ if (!enames[m])
157+ goto fail;
158+ }
159+ }
160+ }
161+
162+ free(eid);
163+ return mixer;
164+
165+fail:
166+ if (eid)
167+ free(eid);
168+ if (mixer)
169+ mixer_close(mixer);
170+ else if (fd >= 0)
171+ close(fd);
172+ return 0;
173+}
174+
175+void mixer_dump(struct mixer *mixer)
176+{
177+ unsigned n, m;
178+
179+ printf(" id iface dev sub idx num perms type name\n");
180+ for (n = 0; n < mixer->count; n++) {
181+ struct snd_ctl_elem_info *ei = mixer->info + n;
182+
183+ printf("%4d %5s %3d %3d %3d %3d %c%c%c%c%c%c%c%c%c %-6s %s",
184+ ei->id.numid, elem_iface_name(ei->id.iface),
185+ ei->id.device, ei->id.subdevice, ei->id.index,
186+ ei->count,
187+ (ei->access & SNDRV_CTL_ELEM_ACCESS_READ) ? 'r' : ' ',
188+ (ei->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ? 'w' : ' ',
189+ (ei->access & SNDRV_CTL_ELEM_ACCESS_VOLATILE) ? 'V' : ' ',
190+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TIMESTAMP) ? 'T' : ' ',
191+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) ? 'R' : ' ',
192+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) ? 'W' : ' ',
193+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) ? 'C' : ' ',
194+ (ei->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) ? 'I' : ' ',
195+ (ei->access & SNDRV_CTL_ELEM_ACCESS_LOCK) ? 'L' : ' ',
196+ elem_type_name(ei->type),
197+ ei->id.name);
198+ switch (ei->type) {
199+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
200+ printf(ei->value.integer.step ?
201+ " { %ld-%ld, %ld }\n" : " { %ld-%ld }",
202+ ei->value.integer.min,
203+ ei->value.integer.max,
204+ ei->value.integer.step);
205+ break;
206+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
207+ printf(ei->value.integer64.step ?
208+ " { %lld-%lld, %lld }\n" : " { %lld-%lld }",
209+ ei->value.integer64.min,
210+ ei->value.integer64.max,
211+ ei->value.integer64.step);
212+ break;
213+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: {
214+ unsigned m;
215+ printf(" { %s=0", mixer->ctl[n].ename[0]);
216+ for (m = 1; m < ei->value.enumerated.items; m++)
217+ printf(", %s=%d", mixer->ctl[n].ename[m],m);
218+ printf(" }");
219+ break;
220+ }
221+ }
222+ printf("\n");
223+ }
224+}
225+
226+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
227+ const char *name, unsigned index)
228+{
229+ unsigned n;
230+ for (n = 0; n < mixer->count; n++) {
231+ if (mixer->info[n].id.index == index) {
232+ if (!strcmp(name, (char*) mixer->info[n].id.name)) {
233+ return mixer->ctl + n;
234+ }
235+ }
236+ }
237+ return 0;
238+}
239+
240+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n)
241+{
242+ if (n < mixer->count)
243+ return mixer->ctl + n;
244+ return 0;
245+}
246+
247+void mixer_ctl_print(struct mixer_ctl *ctl)
248+{
249+ struct snd_ctl_elem_value ev;
250+ unsigned n;
251+
252+ memset(&ev, 0, sizeof(ev));
253+ ev.id.numid = ctl->info->id.numid;
254+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev))
255+ return;
256+ printf("%s:", ctl->info->id.name);
257+
258+ switch (ctl->info->type) {
259+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
260+ for (n = 0; n < ctl->info->count; n++)
261+ printf(" %s", ev.value.integer.value[n] ? "ON" : "OFF");
262+ break;
263+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
264+ for (n = 0; n < ctl->info->count; n++)
265+ printf(" %ld", ev.value.integer.value[n]);
266+ break;
267+ }
268+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
269+ for (n = 0; n < ctl->info->count; n++)
270+ printf(" %lld", ev.value.integer64.value[n]);
271+ break;
272+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
273+ for (n = 0; n < ctl->info->count; n++) {
274+ unsigned v = ev.value.enumerated.item[n];
275+ printf(" %d (%s)", v,
276+ (v < ctl->info->value.enumerated.items) ? ctl->ename[v] : "???");
277+ }
278+ break;
279+ default:
280+ printf(" ???");
281+ }
282+ printf("\n");
283+}
284+
285+static long scale_int(struct snd_ctl_elem_info *ei, unsigned _percent)
286+{
287+ long percent;
288+ long range;
289+
290+ if (_percent > 100)
291+ percent = 100;
292+ else
293+ percent = (long) _percent;
294+
295+ range = (ei->value.integer.max - ei->value.integer.min);
296+
297+ return ei->value.integer.min + (range * percent) / 100LL;
298+}
299+
300+static long long scale_int64(struct snd_ctl_elem_info *ei, unsigned _percent)
301+{
302+ long long percent;
303+ long long range;
304+
305+ if (_percent > 100)
306+ percent = 100;
307+ else
308+ percent = (long) _percent;
309+
310+ range = (ei->value.integer.max - ei->value.integer.min) * 100LL;
311+
312+ return ei->value.integer.min + (range / percent);
313+}
314+
315+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent)
316+{
317+ struct snd_ctl_elem_value ev;
318+ unsigned n;
319+
320+ memset(&ev, 0, sizeof(ev));
321+ ev.id.numid = ctl->info->id.numid;
322+ switch (ctl->info->type) {
323+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
324+ for (n = 0; n < ctl->info->count; n++)
325+ ev.value.integer.value[n] = !!percent;
326+ break;
327+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
328+ long value = scale_int(ctl->info, percent);
329+ for (n = 0; n < ctl->info->count; n++)
330+ ev.value.integer.value[n] = value;
331+ break;
332+ }
333+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: {
334+ long long value = scale_int64(ctl->info, percent);
335+ for (n = 0; n < ctl->info->count; n++)
336+ ev.value.integer64.value[n] = value;
337+ break;
338+ }
339+ default:
340+ errno = EINVAL;
341+ return -1;
342+ }
343+
344+ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
345+}
346+
347+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value)
348+{
349+ unsigned n, max;
350+ struct snd_ctl_elem_value ev;
351+
352+ if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
353+ errno = EINVAL;
354+ return -1;
355+ }
356+
357+ max = ctl->info->value.enumerated.items;
358+ for (n = 0; n < max; n++) {
359+ if (!strcmp(value, ctl->ename[n])) {
360+ memset(&ev, 0, sizeof(ev));
361+ ev.value.enumerated.item[0] = n;
362+ ev.id.numid = ctl->info->id.numid;
363+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev) < 0)
364+ return -1;
365+ return 0;
366+ }
367+ }
368+
369+ errno = EINVAL;
370+ return -1;
371+}
--- /dev/null
+++ b/alsa_pcm.c
@@ -0,0 +1,404 @@
1+/*
2+** Copyright 2010, The Android Open-Source Project
3+**
4+** Licensed under the Apache License, Version 2.0 (the "License");
5+** you may not use this file except in compliance with the License.
6+** You may obtain a copy of the License at
7+**
8+** http://www.apache.org/licenses/LICENSE-2.0
9+**
10+** Unless required by applicable law or agreed to in writing, software
11+** distributed under the License is distributed on an "AS IS" BASIS,
12+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+** See the License for the specific language governing permissions and
14+** limitations under the License.
15+*/
16+
17+#define LOG_TAG "alsa_pcm"
18+//#define LOG_NDEBUG 0
19+#include <cutils/log.h>
20+#include <cutils/config_utils.h>
21+
22+#include <stdio.h>
23+#include <stdlib.h>
24+#include <fcntl.h>
25+#include <stdarg.h>
26+#include <string.h>
27+#include <errno.h>
28+#include <unistd.h>
29+
30+#include <sys/ioctl.h>
31+#include <sys/mman.h>
32+#include <sys/time.h>
33+
34+#include <linux/ioctl.h>
35+
36+#include "alsa_audio.h"
37+
38+#define __force
39+#define __bitwise
40+#define __user
41+#include "asound.h"
42+
43+#define DEBUG 0
44+
45+/* alsa parameter manipulation cruft */
46+
47+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
48+
49+static inline int param_is_mask(int p)
50+{
51+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
52+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
53+}
54+
55+static inline int param_is_interval(int p)
56+{
57+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
58+ (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
59+}
60+
61+static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
62+{
63+ return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
64+}
65+
66+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
67+{
68+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
69+}
70+
71+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
72+{
73+ if (bit >= SNDRV_MASK_MAX)
74+ return;
75+ if (param_is_mask(n)) {
76+ struct snd_mask *m = param_to_mask(p, n);
77+ m->bits[0] = 0;
78+ m->bits[1] = 0;
79+ m->bits[bit >> 5] |= (1 << (bit & 31));
80+ }
81+}
82+
83+static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val)
84+{
85+ if (param_is_interval(n)) {
86+ struct snd_interval *i = param_to_interval(p, n);
87+ i->min = val;
88+ }
89+}
90+
91+static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val)
92+{
93+ if (param_is_interval(n)) {
94+ struct snd_interval *i = param_to_interval(p, n);
95+ i->max = val;
96+ }
97+}
98+
99+static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val)
100+{
101+ if (param_is_interval(n)) {
102+ struct snd_interval *i = param_to_interval(p, n);
103+ i->min = val;
104+ i->max = val;
105+ i->integer = 1;
106+ }
107+}
108+
109+static void param_init(struct snd_pcm_hw_params *p)
110+{
111+ int n;
112+ memset(p, 0, sizeof(*p));
113+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
114+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
115+ struct snd_mask *m = param_to_mask(p, n);
116+ m->bits[0] = ~0;
117+ m->bits[1] = ~0;
118+ }
119+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
120+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
121+ struct snd_interval *i = param_to_interval(p, n);
122+ i->min = 0;
123+ i->max = ~0;
124+ }
125+}
126+
127+/* debugging gunk */
128+
129+#if DEBUG
130+static const char *param_name[PARAM_MAX+1] = {
131+ [SNDRV_PCM_HW_PARAM_ACCESS] = "access",
132+ [SNDRV_PCM_HW_PARAM_FORMAT] = "format",
133+ [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat",
134+
135+ [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits",
136+ [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits",
137+ [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels",
138+ [SNDRV_PCM_HW_PARAM_RATE] = "rate",
139+ [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
140+ [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
141+ [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes",
142+ [SNDRV_PCM_HW_PARAM_PERIODS] = "periods",
143+ [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
144+ [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
145+ [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes",
146+ [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time",
147+};
148+
149+static void param_dump(struct snd_pcm_hw_params *p)
150+{
151+ int n;
152+
153+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
154+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
155+ struct snd_mask *m = param_to_mask(p, n);
156+ LOGV("%s = %08x%08x\n", param_name[n],
157+ m->bits[1], m->bits[0]);
158+ }
159+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
160+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
161+ struct snd_interval *i = param_to_interval(p, n);
162+ LOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n",
163+ param_name[n], i->min, i->max, i->openmin,
164+ i->openmax, i->integer, i->empty);
165+ }
166+ LOGV("info = %08x\n", p->info);
167+ LOGV("msbits = %d\n", p->msbits);
168+ LOGV("rate = %d/%d\n", p->rate_num, p->rate_den);
169+ LOGV("fifo = %d\n", (int) p->fifo_size);
170+}
171+
172+static void info_dump(struct snd_pcm_info *info)
173+{
174+ LOGV("device = %d\n", info->device);
175+ LOGV("subdevice = %d\n", info->subdevice);
176+ LOGV("stream = %d\n", info->stream);
177+ LOGV("card = %d\n", info->card);
178+ LOGV("id = '%s'\n", info->id);
179+ LOGV("name = '%s'\n", info->name);
180+ LOGV("subname = '%s'\n", info->subname);
181+ LOGV("dev_class = %d\n", info->dev_class);
182+ LOGV("dev_subclass = %d\n", info->dev_subclass);
183+ LOGV("subdevices_count = %d\n", info->subdevices_count);
184+ LOGV("subdevices_avail = %d\n", info->subdevices_avail);
185+}
186+#else
187+static void param_dump(struct snd_pcm_hw_params *p) {}
188+static void info_dump(struct snd_pcm_info *info) {}
189+#endif
190+
191+#define PCM_ERROR_MAX 128
192+
193+struct pcm {
194+ int fd;
195+ unsigned flags;
196+ int running:1;
197+ int underruns;
198+ unsigned buffer_size;
199+ char error[PCM_ERROR_MAX];
200+};
201+
202+unsigned pcm_buffer_size(struct pcm *pcm)
203+{
204+ return pcm->buffer_size;
205+}
206+
207+const char* pcm_error(struct pcm *pcm)
208+{
209+ return pcm->error;
210+}
211+
212+static int oops(struct pcm *pcm, int e, const char *fmt, ...)
213+{
214+ va_list ap;
215+ int sz;
216+
217+ va_start(ap, fmt);
218+ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
219+ va_end(ap);
220+ sz = strlen(pcm->error);
221+
222+ if (errno)
223+ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
224+ ": %s", strerror(e));
225+ return -1;
226+}
227+
228+int pcm_write(struct pcm *pcm, void *data, unsigned count)
229+{
230+ struct snd_xferi x;
231+
232+ if (pcm->flags & PCM_IN)
233+ return -EINVAL;
234+
235+ x.buf = data;
236+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
237+
238+ for (;;) {
239+ if (!pcm->running) {
240+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
241+ return oops(pcm, errno, "cannot prepare channel");
242+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
243+ return oops(pcm, errno, "cannot write initial data");
244+ pcm->running = 1;
245+ return 0;
246+ }
247+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
248+ pcm->running = 0;
249+ if (errno == EPIPE) {
250+ /* we failed to make our window -- try to restart */
251+ pcm->underruns++;
252+ continue;
253+ }
254+ return oops(pcm, errno, "cannot write stream data");
255+ }
256+ return 0;
257+ }
258+}
259+
260+int pcm_read(struct pcm *pcm, void *data, unsigned count)
261+{
262+ struct snd_xferi x;
263+
264+ if (!(pcm->flags & PCM_IN))
265+ return -EINVAL;
266+
267+ x.buf = data;
268+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
269+
270+// LOGV("read() %d frames", x.frames);
271+ for (;;) {
272+ if (!pcm->running) {
273+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
274+ return oops(pcm, errno, "cannot prepare channel");
275+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START))
276+ return oops(pcm, errno, "cannot start channel");
277+ pcm->running = 1;
278+ }
279+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
280+ pcm->running = 0;
281+ if (errno == EPIPE) {
282+ /* we failed to make our window -- try to restart */
283+ pcm->underruns++;
284+ continue;
285+ }
286+ return oops(pcm, errno, "cannot read stream data");
287+ }
288+// LOGV("read() got %d frames", x.frames);
289+ return 0;
290+ }
291+}
292+
293+static struct pcm bad_pcm = {
294+ .fd = -1,
295+};
296+
297+int pcm_close(struct pcm *pcm)
298+{
299+ if (pcm == &bad_pcm)
300+ return 0;
301+
302+ if (pcm->fd >= 0)
303+ close(pcm->fd);
304+ pcm->running = 0;
305+ pcm->buffer_size = 0;
306+ pcm->fd = -1;
307+ return 0;
308+}
309+
310+struct pcm *pcm_open(unsigned flags)
311+{
312+ int i;
313+ char dname[32];
314+ struct pcm *pcm;
315+ struct snd_pcm_info info;
316+ struct snd_pcm_hw_params params;
317+ struct snd_pcm_sw_params sparams;
318+ unsigned period_sz;
319+ unsigned period_cnt;
320+
321+ LOGV("pcm_open(0x%08x)",flags);
322+
323+ pcm = calloc(1, sizeof(struct pcm));
324+ if (!pcm)
325+ return &bad_pcm;
326+
327+ LOGV("pcm_open() period sz multiplier %d",
328+ ((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
329+ period_sz = 128 * (((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
330+ LOGV("pcm_open() period cnt %d",
331+ ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN);
332+ period_cnt = ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN;
333+
334+ pcm->flags = flags;
335+ for (i = 0; i < 3; ++i) {
336+ sprintf(dname, "/dev/snd/pcmC%dD0%c", i, (flags & PCM_IN) ? 'c' : 'p');
337+ pcm->fd = open(dname, O_RDWR);
338+ if (pcm->fd >= 0)
339+ break;
340+ oops(pcm, errno, "cannot open device '%s'", dname);
341+ }
342+ if (i == 3)
343+ return pcm;
344+
345+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
346+ oops(pcm, errno, "cannot get info - %s", dname);
347+ goto fail;
348+ }
349+ info_dump(&info);
350+
351+ LOGV("pcm_open() period_cnt %d period_sz %d channels %d",
352+ period_cnt, period_sz, (flags & PCM_MONO) ? 1 : 2);
353+
354+ param_init(&params);
355+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
356+ SNDRV_PCM_ACCESS_RW_INTERLEAVED);
357+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
358+ SNDRV_PCM_FORMAT_S16_LE);
359+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
360+ SNDRV_PCM_SUBFORMAT_STD);
361+ param_set_min(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz);
362+ param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
363+ param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
364+ (flags & PCM_MONO) ? 16 : 32);
365+ param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
366+ (flags & PCM_MONO) ? 1 : 2);
367+ param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt);
368+ param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, 44100);
369+
370+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
371+ oops(pcm, errno, "cannot set hw params");
372+ goto fail;
373+ }
374+ param_dump(&params);
375+
376+ memset(&sparams, 0, sizeof(sparams));
377+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
378+ sparams.period_step = 1;
379+ sparams.avail_min = 1;
380+ sparams.start_threshold = period_cnt * period_sz;
381+ sparams.stop_threshold = period_cnt * period_sz;
382+ sparams.xfer_align = period_sz / 2; /* needed for old kernels */
383+ sparams.silence_size = 0;
384+ sparams.silence_threshold = 0;
385+
386+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
387+ oops(pcm, errno, "cannot set sw params");
388+ goto fail;
389+ }
390+
391+ pcm->buffer_size = period_cnt * period_sz;
392+ pcm->underruns = 0;
393+ return pcm;
394+
395+fail:
396+ close(pcm->fd);
397+ pcm->fd = -1;
398+ return pcm;
399+}
400+
401+int pcm_ready(struct pcm *pcm)
402+{
403+ return pcm->fd >= 0;
404+}
--- /dev/null
+++ b/asound.h
@@ -0,0 +1,813 @@
1+/****************************************************************************
2+ ****************************************************************************
3+ ***
4+ *** This header was automatically generated from a Linux kernel header
5+ *** of the same name, to make information necessary for userspace to
6+ *** call into the kernel available to libc. It contains only constants,
7+ *** structures, and macros generated from the original header, and thus,
8+ *** contains no copyrightable information.
9+ ***
10+ ****************************************************************************
11+ ****************************************************************************/
12+#ifndef __SOUND_ASOUND_H
13+#define __SOUND_ASOUND_H
14+
15+#include <linux/types.h>
16+
17+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
18+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
19+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
20+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
21+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
22+
23+struct snd_aes_iec958 {
24+ unsigned char status[24];
25+ unsigned char subcode[147];
26+ unsigned char pad;
27+ unsigned char dig_subframe[4];
28+};
29+
30+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
31+
32+enum {
33+ SNDRV_HWDEP_IFACE_OPL2 = 0,
34+ SNDRV_HWDEP_IFACE_OPL3,
35+ SNDRV_HWDEP_IFACE_OPL4,
36+ SNDRV_HWDEP_IFACE_SB16CSP,
37+ SNDRV_HWDEP_IFACE_EMU10K1,
38+ SNDRV_HWDEP_IFACE_YSS225,
39+ SNDRV_HWDEP_IFACE_ICS2115,
40+ SNDRV_HWDEP_IFACE_SSCAPE,
41+ SNDRV_HWDEP_IFACE_VX,
42+ SNDRV_HWDEP_IFACE_MIXART,
43+ SNDRV_HWDEP_IFACE_USX2Y,
44+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
45+ SNDRV_HWDEP_IFACE_BLUETOOTH,
46+ SNDRV_HWDEP_IFACE_USX2Y_PCM,
47+ SNDRV_HWDEP_IFACE_PCXHR,
48+ SNDRV_HWDEP_IFACE_SB_RC,
49+ SNDRV_HWDEP_IFACE_HDA,
50+ SNDRV_HWDEP_IFACE_USB_STREAM,
51+
52+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
53+};
54+
55+struct snd_hwdep_info {
56+ unsigned int device;
57+ int card;
58+ unsigned char id[64];
59+ unsigned char name[80];
60+ int iface;
61+ unsigned char reserved[64];
62+};
63+
64+struct snd_hwdep_dsp_status {
65+ unsigned int version;
66+ unsigned char id[32];
67+ unsigned int num_dsps;
68+ unsigned int dsp_loaded;
69+ unsigned int chip_ready;
70+ unsigned char reserved[16];
71+};
72+
73+struct snd_hwdep_dsp_image {
74+ unsigned int index;
75+ unsigned char name[64];
76+ unsigned char __user *image;
77+ size_t length;
78+ unsigned long driver_data;
79+};
80+
81+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
82+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
83+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
84+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
85+
86+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
87+
88+typedef unsigned long snd_pcm_uframes_t;
89+typedef signed long snd_pcm_sframes_t;
90+
91+enum {
92+ SNDRV_PCM_CLASS_GENERIC = 0,
93+ SNDRV_PCM_CLASS_MULTI,
94+ SNDRV_PCM_CLASS_MODEM,
95+ SNDRV_PCM_CLASS_DIGITIZER,
96+
97+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
98+};
99+
100+enum {
101+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
102+ SNDRV_PCM_SUBCLASS_MULTI_MIX,
103+
104+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
105+};
106+
107+enum {
108+ SNDRV_PCM_STREAM_PLAYBACK = 0,
109+ SNDRV_PCM_STREAM_CAPTURE,
110+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
111+};
112+
113+typedef int __bitwise snd_pcm_access_t;
114+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
115+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
116+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
117+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
118+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
119+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
120+
121+typedef int __bitwise snd_pcm_format_t;
122+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
123+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
124+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
125+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
126+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
127+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
128+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
129+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
130+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
131+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
132+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
133+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
134+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
135+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
136+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
137+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
138+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
139+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
140+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
141+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
142+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
143+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
144+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
145+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
146+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
147+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
148+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
149+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
150+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
151+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
152+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
153+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
154+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
155+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
156+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
157+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
158+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
159+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
160+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
161+
162+#ifdef SNDRV_LITTLE_ENDIAN
163+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
164+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
165+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
166+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
167+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
168+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
169+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
170+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
171+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
172+#endif
173+#ifdef SNDRV_BIG_ENDIAN
174+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
175+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
176+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
177+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
178+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
179+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
180+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
181+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
182+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
183+#endif
184+
185+typedef int __bitwise snd_pcm_subformat_t;
186+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
187+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
188+
189+#define SNDRV_PCM_INFO_MMAP 0x00000001
190+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
191+#define SNDRV_PCM_INFO_DOUBLE 0x00000004
192+#define SNDRV_PCM_INFO_BATCH 0x00000010
193+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
194+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
195+#define SNDRV_PCM_INFO_COMPLEX 0x00000400
196+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
197+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
198+#define SNDRV_PCM_INFO_RESUME 0x00040000
199+#define SNDRV_PCM_INFO_PAUSE 0x00080000
200+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
201+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
202+#define SNDRV_PCM_INFO_SYNC_START 0x00400000
203+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
204+
205+typedef int __bitwise snd_pcm_state_t;
206+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
207+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
208+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
209+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
210+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
211+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
212+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
213+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
214+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
215+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
216+
217+enum {
218+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
219+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
220+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
221+};
222+
223+union snd_pcm_sync_id {
224+ unsigned char id[16];
225+ unsigned short id16[8];
226+ unsigned int id32[4];
227+};
228+
229+struct snd_pcm_info {
230+ unsigned int device;
231+ unsigned int subdevice;
232+ int stream;
233+ int card;
234+ unsigned char id[64];
235+ unsigned char name[80];
236+ unsigned char subname[32];
237+ int dev_class;
238+ int dev_subclass;
239+ unsigned int subdevices_count;
240+ unsigned int subdevices_avail;
241+ union snd_pcm_sync_id sync;
242+ unsigned char reserved[64];
243+};
244+
245+typedef int snd_pcm_hw_param_t;
246+#define SNDRV_PCM_HW_PARAM_ACCESS 0
247+#define SNDRV_PCM_HW_PARAM_FORMAT 1
248+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
249+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
250+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
251+
252+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
253+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
254+#define SNDRV_PCM_HW_PARAM_CHANNELS 10
255+#define SNDRV_PCM_HW_PARAM_RATE 11
256+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
257+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
258+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
259+#define SNDRV_PCM_HW_PARAM_PERIODS 15
260+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
261+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
262+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
263+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
264+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
265+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
266+
267+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
268+
269+struct snd_interval {
270+ unsigned int min, max;
271+ unsigned int openmin:1,
272+ openmax:1,
273+ integer:1,
274+ empty:1;
275+};
276+
277+#define SNDRV_MASK_MAX 256
278+
279+struct snd_mask {
280+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
281+};
282+
283+struct snd_pcm_hw_params {
284+ unsigned int flags;
285+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
286+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
287+ struct snd_mask mres[5];
288+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
289+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
290+ struct snd_interval ires[9];
291+ unsigned int rmask;
292+ unsigned int cmask;
293+ unsigned int info;
294+ unsigned int msbits;
295+ unsigned int rate_num;
296+ unsigned int rate_den;
297+ snd_pcm_uframes_t fifo_size;
298+ unsigned char reserved[64];
299+};
300+
301+enum {
302+ SNDRV_PCM_TSTAMP_NONE = 0,
303+ SNDRV_PCM_TSTAMP_ENABLE,
304+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
305+};
306+
307+struct snd_pcm_sw_params {
308+ int tstamp_mode;
309+ unsigned int period_step;
310+ unsigned int sleep_min;
311+ snd_pcm_uframes_t avail_min;
312+ snd_pcm_uframes_t xfer_align;
313+ snd_pcm_uframes_t start_threshold;
314+ snd_pcm_uframes_t stop_threshold;
315+ snd_pcm_uframes_t silence_threshold;
316+ snd_pcm_uframes_t silence_size;
317+ snd_pcm_uframes_t boundary;
318+ unsigned char reserved[64];
319+};
320+
321+struct snd_pcm_channel_info {
322+ unsigned int channel;
323+ __kernel_off_t offset;
324+ unsigned int first;
325+ unsigned int step;
326+};
327+
328+struct snd_pcm_status {
329+ snd_pcm_state_t state;
330+ struct timespec trigger_tstamp;
331+ struct timespec tstamp;
332+ snd_pcm_uframes_t appl_ptr;
333+ snd_pcm_uframes_t hw_ptr;
334+ snd_pcm_sframes_t delay;
335+ snd_pcm_uframes_t avail;
336+ snd_pcm_uframes_t avail_max;
337+ snd_pcm_uframes_t overrange;
338+ snd_pcm_state_t suspended_state;
339+ unsigned char reserved[60];
340+};
341+
342+struct snd_pcm_mmap_status {
343+ snd_pcm_state_t state;
344+ int pad1;
345+ snd_pcm_uframes_t hw_ptr;
346+ struct timespec tstamp;
347+ snd_pcm_state_t suspended_state;
348+};
349+
350+struct snd_pcm_mmap_control {
351+ snd_pcm_uframes_t appl_ptr;
352+ snd_pcm_uframes_t avail_min;
353+};
354+
355+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
356+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
357+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
358+
359+struct snd_pcm_sync_ptr {
360+ unsigned int flags;
361+ union {
362+ struct snd_pcm_mmap_status status;
363+ unsigned char reserved[64];
364+ } s;
365+ union {
366+ struct snd_pcm_mmap_control control;
367+ unsigned char reserved[64];
368+ } c;
369+};
370+
371+struct snd_xferi {
372+ snd_pcm_sframes_t result;
373+ void __user *buf;
374+ snd_pcm_uframes_t frames;
375+};
376+
377+struct snd_xfern {
378+ snd_pcm_sframes_t result;
379+ void __user * __user *bufs;
380+ snd_pcm_uframes_t frames;
381+};
382+
383+enum {
384+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
385+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
386+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
387+};
388+
389+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
390+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
391+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
392+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
393+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
394+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
395+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
396+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
397+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
398+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
399+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
400+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
401+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
402+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
403+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
404+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
405+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
406+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
407+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
408+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
409+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
410+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
411+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
412+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
413+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
414+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
415+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
416+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
417+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
418+
419+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
420+
421+enum {
422+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
423+ SNDRV_RAWMIDI_STREAM_INPUT,
424+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
425+};
426+
427+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
428+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
429+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
430+
431+struct snd_rawmidi_info {
432+ unsigned int device;
433+ unsigned int subdevice;
434+ int stream;
435+ int card;
436+ unsigned int flags;
437+ unsigned char id[64];
438+ unsigned char name[80];
439+ unsigned char subname[32];
440+ unsigned int subdevices_count;
441+ unsigned int subdevices_avail;
442+ unsigned char reserved[64];
443+};
444+
445+struct snd_rawmidi_params {
446+ int stream;
447+ size_t buffer_size;
448+ size_t avail_min;
449+ unsigned int no_active_sensing: 1;
450+ unsigned char reserved[16];
451+};
452+
453+struct snd_rawmidi_status {
454+ int stream;
455+ struct timespec tstamp;
456+ size_t avail;
457+ size_t xruns;
458+ unsigned char reserved[16];
459+};
460+
461+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
462+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
463+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
464+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
465+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
466+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
467+
468+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
469+
470+enum {
471+ SNDRV_TIMER_CLASS_NONE = -1,
472+ SNDRV_TIMER_CLASS_SLAVE = 0,
473+ SNDRV_TIMER_CLASS_GLOBAL,
474+ SNDRV_TIMER_CLASS_CARD,
475+ SNDRV_TIMER_CLASS_PCM,
476+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
477+};
478+
479+enum {
480+ SNDRV_TIMER_SCLASS_NONE = 0,
481+ SNDRV_TIMER_SCLASS_APPLICATION,
482+ SNDRV_TIMER_SCLASS_SEQUENCER,
483+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
484+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
485+};
486+
487+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
488+#define SNDRV_TIMER_GLOBAL_RTC 1
489+#define SNDRV_TIMER_GLOBAL_HPET 2
490+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
491+
492+#define SNDRV_TIMER_FLG_SLAVE (1<<0)
493+
494+struct snd_timer_id {
495+ int dev_class;
496+ int dev_sclass;
497+ int card;
498+ int device;
499+ int subdevice;
500+};
501+
502+struct snd_timer_ginfo {
503+ struct snd_timer_id tid;
504+ unsigned int flags;
505+ int card;
506+ unsigned char id[64];
507+ unsigned char name[80];
508+ unsigned long reserved0;
509+ unsigned long resolution;
510+ unsigned long resolution_min;
511+ unsigned long resolution_max;
512+ unsigned int clients;
513+ unsigned char reserved[32];
514+};
515+
516+struct snd_timer_gparams {
517+ struct snd_timer_id tid;
518+ unsigned long period_num;
519+ unsigned long period_den;
520+ unsigned char reserved[32];
521+};
522+
523+struct snd_timer_gstatus {
524+ struct snd_timer_id tid;
525+ unsigned long resolution;
526+ unsigned long resolution_num;
527+ unsigned long resolution_den;
528+ unsigned char reserved[32];
529+};
530+
531+struct snd_timer_select {
532+ struct snd_timer_id id;
533+ unsigned char reserved[32];
534+};
535+
536+struct snd_timer_info {
537+ unsigned int flags;
538+ int card;
539+ unsigned char id[64];
540+ unsigned char name[80];
541+ unsigned long reserved0;
542+ unsigned long resolution;
543+ unsigned char reserved[64];
544+};
545+
546+#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
547+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
548+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
549+
550+struct snd_timer_params {
551+ unsigned int flags;
552+ unsigned int ticks;
553+ unsigned int queue_size;
554+ unsigned int reserved0;
555+ unsigned int filter;
556+ unsigned char reserved[60];
557+};
558+
559+struct snd_timer_status {
560+ struct timespec tstamp;
561+ unsigned int resolution;
562+ unsigned int lost;
563+ unsigned int overrun;
564+ unsigned int queue;
565+ unsigned char reserved[64];
566+};
567+
568+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
569+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
570+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
571+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
572+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
573+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
574+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
575+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
576+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
577+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
578+
579+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
580+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
581+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
582+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
583+
584+struct snd_timer_read {
585+ unsigned int resolution;
586+ unsigned int ticks;
587+};
588+
589+enum {
590+ SNDRV_TIMER_EVENT_RESOLUTION = 0,
591+ SNDRV_TIMER_EVENT_TICK,
592+ SNDRV_TIMER_EVENT_START,
593+ SNDRV_TIMER_EVENT_STOP,
594+ SNDRV_TIMER_EVENT_CONTINUE,
595+ SNDRV_TIMER_EVENT_PAUSE,
596+ SNDRV_TIMER_EVENT_EARLY,
597+ SNDRV_TIMER_EVENT_SUSPEND,
598+ SNDRV_TIMER_EVENT_RESUME,
599+
600+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
601+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
602+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
603+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
604+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
605+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
606+};
607+
608+struct snd_timer_tread {
609+ int event;
610+ struct timespec tstamp;
611+ unsigned int val;
612+};
613+
614+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
615+
616+struct snd_ctl_card_info {
617+ int card;
618+ int pad;
619+ unsigned char id[16];
620+ unsigned char driver[16];
621+ unsigned char name[32];
622+ unsigned char longname[80];
623+ unsigned char reserved_[16];
624+ unsigned char mixername[80];
625+ unsigned char components[128];
626+};
627+
628+typedef int __bitwise snd_ctl_elem_type_t;
629+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
630+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
631+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
632+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
633+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
634+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
635+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
636+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
637+
638+typedef int __bitwise snd_ctl_elem_iface_t;
639+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
640+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
641+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
642+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
643+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
644+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
645+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
646+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
647+
648+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
649+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
650+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
651+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
652+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
653+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
654+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
655+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
656+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
657+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
658+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
659+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
660+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
661+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
662+
663+#define SNDRV_CTL_POWER_D0 0x0000
664+#define SNDRV_CTL_POWER_D1 0x0100
665+#define SNDRV_CTL_POWER_D2 0x0200
666+#define SNDRV_CTL_POWER_D3 0x0300
667+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
668+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
669+
670+struct snd_ctl_elem_id {
671+ unsigned int numid;
672+ snd_ctl_elem_iface_t iface;
673+ unsigned int device;
674+ unsigned int subdevice;
675+ unsigned char name[44];
676+ unsigned int index;
677+};
678+
679+struct snd_ctl_elem_list {
680+ unsigned int offset;
681+ unsigned int space;
682+ unsigned int used;
683+ unsigned int count;
684+ struct snd_ctl_elem_id __user *pids;
685+ unsigned char reserved[50];
686+};
687+
688+struct snd_ctl_elem_info {
689+ struct snd_ctl_elem_id id;
690+ snd_ctl_elem_type_t type;
691+ unsigned int access;
692+ unsigned int count;
693+ __kernel_pid_t owner;
694+ union {
695+ struct {
696+ long min;
697+ long max;
698+ long step;
699+ } integer;
700+ struct {
701+ long long min;
702+ long long max;
703+ long long step;
704+ } integer64;
705+ struct {
706+ unsigned int items;
707+ unsigned int item;
708+ char name[64];
709+ } enumerated;
710+ unsigned char reserved[128];
711+ } value;
712+ union {
713+ unsigned short d[4];
714+ unsigned short *d_ptr;
715+ } dimen;
716+ unsigned char reserved[64-4*sizeof(unsigned short)];
717+};
718+
719+struct snd_ctl_elem_value {
720+ struct snd_ctl_elem_id id;
721+ unsigned int indirect: 1;
722+ union {
723+ union {
724+ long value[128];
725+ long *value_ptr;
726+ } integer;
727+ union {
728+ long long value[64];
729+ long long *value_ptr;
730+ } integer64;
731+ union {
732+ unsigned int item[128];
733+ unsigned int *item_ptr;
734+ } enumerated;
735+ union {
736+ unsigned char data[512];
737+ unsigned char *data_ptr;
738+ } bytes;
739+ struct snd_aes_iec958 iec958;
740+ } value;
741+ struct timespec tstamp;
742+ unsigned char reserved[128-sizeof(struct timespec)];
743+};
744+
745+struct snd_ctl_tlv {
746+ unsigned int numid;
747+ unsigned int length;
748+ unsigned int tlv[0];
749+};
750+
751+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
752+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
753+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
754+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
755+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
756+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
757+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
758+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
759+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
760+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
761+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
762+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
763+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
764+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
765+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
766+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
767+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
768+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
769+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
770+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
771+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
772+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
773+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
774+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
775+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
776+
777+enum sndrv_ctl_event_type {
778+ SNDRV_CTL_EVENT_ELEM = 0,
779+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
780+};
781+
782+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
783+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
784+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
785+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
786+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
787+
788+struct snd_ctl_event {
789+ int type;
790+ union {
791+ struct {
792+ unsigned int mask;
793+ struct snd_ctl_elem_id id;
794+ } elem;
795+ unsigned char data8[60];
796+ } data;
797+};
798+
799+#define SNDRV_CTL_NAME_NONE ""
800+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
801+#define SNDRV_CTL_NAME_CAPTURE "Capture "
802+
803+#define SNDRV_CTL_NAME_IEC958_NONE ""
804+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
805+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
806+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
807+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
808+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
809+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
810+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
811+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
812+
813+#endif