summaryrefslogtreecommitdiffstats
path: root/libaudio2
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2010-10-10 04:50:45 -0700
committerEric Laurent <elaurent@google.com>2010-10-10 15:59:51 -0700
commit594a71f6df53f42386d5997b38a392f2b566194d (patch)
tree32f9e4abeae7dbd8db5a434c4c011018d0f0a168 /libaudio2
parent3732d0feeebed2031fabe7ff51533eacafcce626 (diff)
downloaddevice_samsung_crespo-594a71f6df53f42386d5997b38a392f2b566194d.zip
device_samsung_crespo-594a71f6df53f42386d5997b38a392f2b566194d.tar.gz
device_samsung_crespo-594a71f6df53f42386d5997b38a392f2b566194d.tar.bz2
libaudio2: this time without libalsa
- commandline testright aplay/arec/amix works - audiohardware not yet tested - audiohardware needs input stream plumbing and real routing support, etc Change-Id: Ie4f86fe7aed906127f2f844dac7d5bd92380cd4e
Diffstat (limited to 'libaudio2')
-rw-r--r--libaudio2/Android.mk49
-rw-r--r--libaudio2/AudioHardware.cpp330
-rw-r--r--libaudio2/AudioHardware.h165
-rw-r--r--libaudio2/AudioPolicyManager.cpp45
-rw-r--r--libaudio2/AudioPolicyManager.h46
-rw-r--r--libaudio2/alsa_audio.h70
-rw-r--r--libaudio2/alsa_mixer.c371
-rw-r--r--libaudio2/alsa_pcm.c390
-rw-r--r--libaudio2/amix.c78
-rw-r--r--libaudio2/aplay.c140
-rw-r--r--libaudio2/arec.c128
-rw-r--r--libaudio2/asound.h814
12 files changed, 2626 insertions, 0 deletions
diff --git a/libaudio2/Android.mk b/libaudio2/Android.mk
new file mode 100644
index 0000000..53979f3
--- /dev/null
+++ b/libaudio2/Android.mk
@@ -0,0 +1,49 @@
+LOCAL_PATH:= $(call my-dir)
+
+ifeq ($(TARGET_DEVICE),crespo)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= aplay.c alsa_pcm.c alsa_mixer.c
+LOCAL_MODULE:= aplay
+LOCAL_SHARED_LIBRARIES:= libc
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= arec.c alsa_pcm.c
+LOCAL_MODULE:= arec
+LOCAL_SHARED_LIBRARIES:= libc
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= amix.c alsa_mixer.c
+LOCAL_MODULE:= amix
+LOCAL_SHARED_LIBRARIES := libc
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+ifneq ($(BOARD_USES_ALSA_AUDIO),true)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= AudioHardware.cpp alsa_mixer.c alsa_pcm.c
+LOCAL_MODULE:= libaudio
+LOCAL_STATIC_LIBRARIES:= libaudiointerface
+LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+ LOCAL_SHARED_LIBRARIES += liba2dp
+endif
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= AudioPolicyManager.cpp
+LOCAL_MODULE:= libaudiopolicy
+LOCAL_STATIC_LIBRARIES:= libaudiopolicybase
+LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+ LOCAL_CFLAGS += -DWITH_A2DP
+endif
+include $(BUILD_SHARED_LIBRARY)
+
+endif
+endif
diff --git a/libaudio2/AudioHardware.cpp b/libaudio2/AudioHardware.cpp
new file mode 100644
index 0000000..c0d20da
--- /dev/null
+++ b/libaudio2/AudioHardware.cpp
@@ -0,0 +1,330 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <math.h>
+
+#define LOG_TAG "AudioHardware"
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+
+#include "AudioHardware.h"
+#include <media/AudioRecord.h>
+
+extern "C" {
+#include "alsa_audio.h"
+}
+
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+AudioHardware::AudioHardware() :
+ mInit(false), mMicMute(true), mOutput(0)
+{
+ mInit = true;
+}
+
+AudioHardware::~AudioHardware()
+{
+ closeOutputStream((AudioStreamOut*)mOutput);
+ mInit = false;
+}
+
+status_t AudioHardware::initCheck()
+{
+ return mInit ? NO_ERROR : NO_INIT;
+}
+
+AudioStreamOut* AudioHardware::openOutputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status)
+{
+ { // scope for the lock
+ Mutex::Autolock lock(mLock);
+
+ // only one output stream allowed
+ if (mOutput) {
+ if (status) {
+ *status = INVALID_OPERATION;
+ }
+ return 0;
+ }
+
+ AudioStreamOutALSA* out = new AudioStreamOutALSA();
+
+ status_t rc = out->set(this, devices, format, channels, sampleRate);
+ if (rc) {
+ *status = rc;
+ }
+ if (rc == NO_ERROR) {
+ mOutput = out;
+ } else {
+ delete out;
+ }
+ }
+ return mOutput;
+}
+
+void AudioHardware::closeOutputStream(AudioStreamOut* out) {
+ Mutex::Autolock lock(mLock);
+ if (mOutput == 0 || mOutput != out) {
+ LOGW("Attempt to close invalid output stream");
+ } else {
+ delete mOutput;
+ mOutput = 0;
+ }
+}
+
+AudioStreamIn* AudioHardware::openInputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status,
+ AudioSystem::audio_in_acoustics acoustic_flags)
+{
+ return 0;
+}
+
+void AudioHardware::closeInputStream(AudioStreamIn* in) {
+}
+
+status_t AudioHardware::setMode(int mode)
+{
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setMicMute(bool state)
+{
+ return NO_ERROR;
+}
+
+status_t AudioHardware::getMicMute(bool* state)
+{
+ *state = mMicMute;
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setParameters(const String8& keyValuePairs)
+{
+ return NO_ERROR;
+}
+
+String8 AudioHardware::getParameters(const String8& keys)
+{
+ AudioParameter request = AudioParameter(keys);
+ AudioParameter reply = AudioParameter();
+
+ LOGV("getParameters() %s", keys.string());
+
+ return reply.toString();
+}
+
+size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+ return 4096;
+}
+
+status_t AudioHardware::setVoiceVolume(float v)
+{
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setMasterVolume(float v)
+{
+ LOGI("Set master volume to %f.\n", v);
+ // We return an error code here to let the audioflinger do in-software
+ // volume on top of the maximum volume that we set through the SND API.
+ // return error - software mixer will handle it
+ return -1;
+}
+
+status_t AudioHardware::dump(int fd, const Vector<String16>& args)
+{
+ return NO_ERROR;
+}
+
+AudioHardware::AudioStreamOutALSA::AudioStreamOutALSA() :
+ mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0), mStartCount(0), mRetryCount(0),
+ mStandby(true), mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS),
+ mSampleRate(AUDIO_HW_OUT_SAMPLERATE), mBufferSize(AUDIO_HW_OUT_BUFSZ)
+{
+}
+
+status_t AudioHardware::AudioStreamOutALSA::set(
+ AudioHardware* hw, uint32_t devices, int *pFormat,
+ uint32_t *pChannels, uint32_t *pRate)
+{
+ int lFormat = pFormat ? *pFormat : 0;
+ uint32_t lChannels = pChannels ? *pChannels : 0;
+ uint32_t lRate = pRate ? *pRate : 0;
+
+ mHardware = hw;
+ mDevices = devices;
+
+ // fix up defaults
+ if (lFormat == 0) lFormat = format();
+ if (lChannels == 0) lChannels = channels();
+ if (lRate == 0) lRate = sampleRate();
+
+ // check values
+ if ((lFormat != format()) ||
+ (lChannels != channels()) ||
+ (lRate != sampleRate())) {
+ if (pFormat) *pFormat = format();
+ if (pChannels) *pChannels = channels();
+ if (pRate) *pRate = sampleRate();
+ return BAD_VALUE;
+ }
+
+ if (pFormat) *pFormat = lFormat;
+ if (pChannels) *pChannels = lChannels;
+ if (pRate) *pRate = lRate;
+
+ mChannels = lChannels;
+ mSampleRate = lRate;
+ mBufferSize = 4096;
+
+ return NO_ERROR;
+}
+
+AudioHardware::AudioStreamOutALSA::~AudioStreamOutALSA()
+{
+ standby();
+}
+
+ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes)
+{
+ // LOGD("AudioStreamOutALSA::write(%p, %u)", buffer, bytes);
+ status_t status = NO_INIT;
+ const uint8_t* p = static_cast<const uint8_t*>(buffer);
+ int ret;
+
+ if (mStandby) {
+ LOGV("open pcm_out driver");
+
+ next_route = "SPK";
+
+ mPcm = pcm_open(PCM_OUT);
+ if (!pcm_ready(mPcm)) {
+ LOGE("cannot open pcm_out driver: %s\n", pcm_error(mPcm));
+ pcm_close(mPcm);
+ mPcm = 0;
+ goto Error;
+ }
+
+ mMixer = mixer_open();
+ if (mMixer)
+ mRouteCtl = mixer_get_control(mMixer, "Playback Path", 0);
+
+#if 0
+ LOGV("set pcm_out config");
+ config.channel_count = AudioSystem::popCount(channels());
+ config.sample_rate = mSampleRate;
+ config.buffer_size = mBufferSize;
+ config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
+// config.codec_type = CODEC_TYPE_PCM;
+ status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
+ if (status < 0) {
+ LOGE("Cannot set config");
+ goto Error;
+ }
+
+ LOGV("buffer_size: %u", config.buffer_size);
+ LOGV("buffer_count: %u", config.buffer_count);
+ LOGV("channel_count: %u", config.channel_count);
+ LOGV("sample_rate: %u", config.sample_rate);
+#endif
+
+ mStandby = false;
+ }
+
+ ret = pcm_write(mPcm,(void*) p, bytes);
+ if (ret == 0) {
+ if (next_route && mRouteCtl) {
+ mixer_ctl_select(mRouteCtl, next_route);
+ next_route = 0;
+ }
+ return bytes;
+ }
+ LOGW("write error: %d", errno);
+ status = -errno;
+
+Error:
+ standby();
+
+ // Simulate audio output timing in case of error
+ usleep(bytes * 1000000 / frameSize() / sampleRate());
+
+ return status;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::standby()
+{
+ if (mPcm) {
+ pcm_close(mPcm);
+ mPcm = 0;
+ }
+ if (mMixer) {
+ mixer_close(mMixer);
+ mMixer = 0;
+ if (mRouteCtl) {
+ mRouteCtl = 0;
+ }
+ }
+ mStandby = true;
+ LOGI("AudioHardware pcm playback is going to standby.");
+ return NO_ERROR;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::dump(int fd, const Vector<String16>& args)
+{
+ return NO_ERROR;
+}
+
+bool AudioHardware::AudioStreamOutALSA::checkStandby()
+{
+ return mStandby;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
+{
+ return NO_ERROR;
+}
+
+String8 AudioHardware::AudioStreamOutALSA::getParameters(const String8& keys)
+{
+ AudioParameter param = AudioParameter(keys);
+ LOGV("AudioStreamOutALSA::getParameters() %s", param.toString().string());
+ return param.toString();
+}
+
+status_t AudioHardware::AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrames)
+{
+ return INVALID_OPERATION;
+}
+
+extern "C" AudioHardwareInterface* createAudioHardware(void) {
+ return new AudioHardware();
+}
+
+}; // namespace android
diff --git a/libaudio2/AudioHardware.h b/libaudio2/AudioHardware.h
new file mode 100644
index 0000000..9bdfe2f
--- /dev/null
+++ b/libaudio2/AudioHardware.h
@@ -0,0 +1,165 @@
+/*
+** Copyright 2008, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_AUDIO_HARDWARE_H
+#define ANDROID_AUDIO_HARDWARE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/SortedVector.h>
+
+#include <hardware_legacy/AudioHardwareBase.h>
+
+extern "C" {
+ struct pcm;
+ struct mixer;
+ struct mixer_ctl;
+};
+
+namespace android {
+
+#define CODEC_TYPE_PCM 0
+#define PCM_FILL_BUFFER_COUNT 1
+// Number of buffers in audio driver for output
+#define AUDIO_HW_NUM_OUT_BUF 2
+
+// TODO: determine actual audio DSP and hardware latency
+// Additionnal latency introduced by audio DSP and hardware in ms
+#define AUDIO_HW_OUT_LATENCY_MS 0
+// Default audio output sample rate
+#define AUDIO_HW_OUT_SAMPLERATE 44100
+// Default audio output channel mask
+#define AUDIO_HW_OUT_CHANNELS (AudioSystem::CHANNEL_OUT_STEREO)
+// Default audio output sample format
+#define AUDIO_HW_OUT_FORMAT (AudioSystem::PCM_16_BIT)
+// Default audio output buffer size
+#define AUDIO_HW_OUT_BUFSZ 4096
+
+#if 0
+// Default audio input sample rate
+#define AUDIO_HW_IN_SAMPLERATE 8000
+// Default audio input channel mask
+#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO)
+// Default audio input sample format
+#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT)
+// Default audio input buffer size
+#define AUDIO_HW_IN_BUFSZ 256
+
+// Maximum voice volume
+#define VOICE_VOLUME_MAX 5
+#endif
+
+class AudioHardware : public AudioHardwareBase
+{
+ class AudioStreamOutALSA;
+public:
+ AudioHardware();
+ virtual ~AudioHardware();
+ virtual status_t initCheck();
+
+ virtual status_t setVoiceVolume(float volume);
+ virtual status_t setMasterVolume(float volume);
+
+ virtual status_t setMode(int mode);
+
+ virtual status_t setMicMute(bool state);
+ virtual status_t getMicMute(bool* state);
+
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys);
+
+ virtual AudioStreamOut* openOutputStream(
+ uint32_t devices, int *format=0, uint32_t *channels=0,
+ uint32_t *sampleRate=0, status_t *status=0);
+
+ virtual AudioStreamIn* openInputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status,
+ AudioSystem::audio_in_acoustics acoustics);
+
+ virtual void closeOutputStream(AudioStreamOut* out);
+ virtual void closeInputStream(AudioStreamIn* in);
+
+ virtual size_t getInputBufferSize(
+ uint32_t sampleRate, int format, int channelCount);
+
+ void clearCurDevice() { }
+
+protected:
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+private:
+ bool mInit;
+ bool mMicMute;
+ AudioStreamOutALSA *mOutput;
+ Mutex mLock;
+ struct mixer *mMixer;
+
+ class AudioStreamOutALSA : public AudioStreamOut
+ {
+ public:
+ AudioStreamOutALSA();
+ virtual ~AudioStreamOutALSA();
+ status_t set(AudioHardware* mHardware,
+ uint32_t devices,
+ int *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pRate);
+ virtual uint32_t sampleRate()
+ const { return mSampleRate; }
+ virtual size_t bufferSize()
+ const { return mBufferSize; }
+ virtual uint32_t channels()
+ const { return mChannels; }
+ virtual int format()
+ const { return AUDIO_HW_OUT_FORMAT; }
+ virtual uint32_t latency()
+ const { return (1000 * AUDIO_HW_NUM_OUT_BUF *
+ (bufferSize()/frameSize()))/sampleRate() +
+ AUDIO_HW_OUT_LATENCY_MS; }
+ virtual status_t setVolume(float left, float right)
+ { return INVALID_OPERATION; }
+ virtual ssize_t write(const void* buffer, size_t bytes);
+ virtual status_t standby();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+ bool checkStandby();
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys);
+ uint32_t devices()
+ { return mDevices; }
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
+
+ private:
+ AudioHardware* mHardware;
+ struct pcm *mPcm;
+ struct mixer *mMixer;
+ struct mixer_ctl *mRouteCtl;
+ const char *next_route;
+ int mStartCount;
+ int mRetryCount;
+ bool mStandby;
+ uint32_t mDevices;
+ uint32_t mChannels;
+ uint32_t mSampleRate;
+ size_t mBufferSize;
+ };
+};
+
+}; // namespace android
+
+#endif
diff --git a/libaudio2/AudioPolicyManager.cpp b/libaudio2/AudioPolicyManager.cpp
new file mode 100644
index 0000000..41c0fd0
--- /dev/null
+++ b/libaudio2/AudioPolicyManager.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioPolicyManager"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include "AudioPolicyManager.h"
+#include <media/mediarecorder.h>
+
+namespace android {
+
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManager for crespo platform
+// Common audio policy manager code is implemented in AudioPolicyManagerBase class
+// ----------------------------------------------------------------------------
+
+// --- class factory
+
+
+extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+{
+ return new AudioPolicyManager(clientInterface);
+}
+
+extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
+{
+ delete interface;
+}
+
+}; // namespace android
diff --git a/libaudio2/AudioPolicyManager.h b/libaudio2/AudioPolicyManager.h
new file mode 100644
index 0000000..03141e5
--- /dev/null
+++ b/libaudio2/AudioPolicyManager.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Timers.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <hardware_legacy/AudioPolicyManagerBase.h>
+
+
+namespace android {
+
+class AudioPolicyManager: public AudioPolicyManagerBase
+{
+
+public:
+ AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+ : AudioPolicyManagerBase(clientInterface) {}
+
+ virtual ~AudioPolicyManager() {}
+
+protected:
+ // true is current platform implements a back microphone
+ virtual bool hasBackMicrophone() const { return false; }
+#ifdef WITH_A2DP
+ // true is current platform supports duplication of notifications and ringtones over A2DP output
+ virtual bool a2dpUsedForSonification() const { return true; }
+#endif
+
+};
+};
diff --git a/libaudio2/alsa_audio.h b/libaudio2/alsa_audio.h
new file mode 100644
index 0000000..ecc78a9
--- /dev/null
+++ b/libaudio2/alsa_audio.h
@@ -0,0 +1,70 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef _AUDIO_H_
+#define _AUDIO_H_
+
+struct pcm;
+
+#define PCM_OUT 0x00000000
+#define PCM_IN 0x10000000
+
+#define PCM_STEREO 0x00000000
+#define PCM_MONO 0x01000000
+
+#define PCM_44100HZ 0x00000000
+#define PCM_48000HZ 0x00100000
+#define PCM_8000HZ 0x00200000
+#define PCM_RATE_MASK 0x00F00000
+
+/* Acquire/release a pcm channel.
+ * Returns non-zero on error
+ */
+struct pcm *pcm_open(unsigned flags);
+int pcm_close(struct pcm *pcm);
+int pcm_ready(struct pcm *pcm);
+
+/* Returns a human readable reason for the last error. */
+const char *pcm_error(struct pcm *pcm);
+
+/* Returns the buffer size (int bytes) that should be used for pcm_write.
+ * This will be 1/2 of the actual fifo size.
+ */
+unsigned pcm_buffer_size(struct pcm *pcm);
+
+/* Write data to the fifo.
+ * Will start playback on the first write or on a write that
+ * occurs after a fifo underrun.
+ */
+int pcm_write(struct pcm *pcm, void *data, unsigned count);
+int pcm_read(struct pcm *pcm, void *data, unsigned count);
+
+struct mixer;
+struct mixer_ctl;
+
+struct mixer *mixer_open(void);
+void mixer_close(struct mixer *mixer);
+void mixer_dump(struct mixer *mixer);
+
+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
+ const char *name, unsigned index);
+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n);
+
+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent);
+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value);
+void mixer_ctl_print(struct mixer_ctl *ctl);
+
+#endif
diff --git a/libaudio2/alsa_mixer.c b/libaudio2/alsa_mixer.c
new file mode 100644
index 0000000..3036ef8
--- /dev/null
+++ b/libaudio2/alsa_mixer.c
@@ -0,0 +1,371 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <linux/ioctl.h>
+#define __force
+#define __bitwise
+#define __user
+#include "asound.h"
+
+#include "alsa_audio.h"
+
+static const char *elem_iface_name(snd_ctl_elem_iface_t n)
+{
+ switch (n) {
+ case SNDRV_CTL_ELEM_IFACE_CARD: return "CARD";
+ case SNDRV_CTL_ELEM_IFACE_HWDEP: return "HWDEP";
+ case SNDRV_CTL_ELEM_IFACE_MIXER: return "MIXER";
+ case SNDRV_CTL_ELEM_IFACE_PCM: return "PCM";
+ case SNDRV_CTL_ELEM_IFACE_RAWMIDI: return "MIDI";
+ case SNDRV_CTL_ELEM_IFACE_TIMER: return "TIMER";
+ case SNDRV_CTL_ELEM_IFACE_SEQUENCER: return "SEQ";
+ default: return "???";
+ }
+}
+
+static const char *elem_type_name(snd_ctl_elem_type_t n)
+{
+ switch (n) {
+ case SNDRV_CTL_ELEM_TYPE_NONE: return "NONE";
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT32";
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
+ case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTES";
+ case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
+ default: return "???";
+ }
+}
+
+
+struct mixer_ctl {
+ struct mixer *mixer;
+ struct snd_ctl_elem_info *info;
+ char **ename;
+};
+
+struct mixer {
+ int fd;
+ struct snd_ctl_elem_info *info;
+ struct mixer_ctl *ctl;
+ unsigned count;
+};
+
+void mixer_close(struct mixer *mixer)
+{
+ unsigned n,m;
+
+ if (mixer->fd >= 0)
+ close(mixer->fd);
+
+ if (mixer->ctl) {
+ for (n = 0; n < mixer->count; n++) {
+ if (mixer->ctl[n].ename) {
+ unsigned max = mixer->ctl[n].info->value.enumerated.items;
+ for (m = 0; m < max; m++)
+ free(mixer->ctl[n].ename[m]);
+ free(mixer->ctl[n].ename);
+ }
+ }
+ free(mixer->ctl);
+ }
+
+ if (mixer->info)
+ free(mixer->info);
+
+ free(mixer);
+}
+
+struct mixer *mixer_open(void)
+{
+ struct snd_ctl_elem_list elist;
+ struct snd_ctl_elem_info tmp;
+ struct snd_ctl_elem_id *eid = NULL;
+ struct mixer *mixer = NULL;
+ unsigned n, m;
+ int fd;
+
+ fd = open("/dev/snd/controlC0", O_RDWR);
+ if (fd < 0)
+ return 0;
+
+ memset(&elist, 0, sizeof(elist));
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ mixer = calloc(1, sizeof(*mixer));
+ if (!mixer)
+ goto fail;
+
+ mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
+ mixer->info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
+ if (!mixer->ctl || !mixer->info)
+ goto fail;
+
+ eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
+ if (!eid)
+ goto fail;
+
+ mixer->count = elist.count;
+ mixer->fd = fd;
+ elist.space = mixer->count;
+ elist.pids = eid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ for (n = 0; n < mixer->count; n++) {
+ struct snd_ctl_elem_info *ei = mixer->info + n;
+ ei->id.numid = eid[n].numid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
+ goto fail;
+ mixer->ctl[n].info = ei;
+ mixer->ctl[n].mixer = mixer;
+ if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
+ if (!enames)
+ goto fail;
+ mixer->ctl[n].ename = enames;
+ for (m = 0; m < ei->value.enumerated.items; m++) {
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.id.numid = ei->id.numid;
+ tmp.value.enumerated.item = m;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
+ goto fail;
+ enames[m] = strdup(tmp.value.enumerated.name);
+ if (!enames[m])
+ goto fail;
+ }
+ }
+ }
+
+ free(eid);
+ return mixer;
+
+fail:
+ if (eid)
+ free(eid);
+ if (mixer)
+ mixer_close(mixer);
+ else if (fd >= 0)
+ close(fd);
+ return 0;
+}
+
+void mixer_dump(struct mixer *mixer)
+{
+ unsigned n, m;
+
+ printf(" id iface dev sub idx num perms type name\n");
+ for (n = 0; n < mixer->count; n++) {
+ struct snd_ctl_elem_info *ei = mixer->info + n;
+
+ printf("%4d %5s %3d %3d %3d %3d %c%c%c%c%c%c%c%c%c %-6s %s",
+ ei->id.numid, elem_iface_name(ei->id.iface),
+ ei->id.device, ei->id.subdevice, ei->id.index,
+ ei->count,
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_READ) ? 'r' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ? 'w' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_VOLATILE) ? 'V' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TIMESTAMP) ? 'T' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) ? 'R' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) ? 'W' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) ? 'C' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) ? 'I' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_LOCK) ? 'L' : ' ',
+ elem_type_name(ei->type),
+ ei->id.name);
+ switch (ei->type) {
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ printf(ei->value.integer.step ?
+ " { %ld-%ld, %ld }\n" : " { %ld-%ld }",
+ ei->value.integer.min,
+ ei->value.integer.max,
+ ei->value.integer.step);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ printf(ei->value.integer64.step ?
+ " { %lld-%lld, %lld }\n" : " { %lld-%lld }",
+ ei->value.integer64.min,
+ ei->value.integer64.max,
+ ei->value.integer64.step);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: {
+ unsigned m;
+ printf(" { %s=0", mixer->ctl[n].ename[0]);
+ for (m = 1; m < ei->value.enumerated.items; m++)
+ printf(", %s=%d", mixer->ctl[n].ename[m],m);
+ printf(" }");
+ break;
+ }
+ }
+ printf("\n");
+ }
+}
+
+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
+ const char *name, unsigned index)
+{
+ unsigned n;
+ for (n = 0; n < mixer->count; n++) {
+ if (mixer->info[n].id.index == index) {
+ if (!strcmp(name, (char*) mixer->info[n].id.name)) {
+ return mixer->ctl + n;
+ }
+ }
+ }
+ return 0;
+}
+
+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n)
+{
+ if (n < mixer->count)
+ return mixer->ctl + n;
+ return 0;
+}
+
+void mixer_ctl_print(struct mixer_ctl *ctl)
+{
+ struct snd_ctl_elem_value ev;
+ unsigned n;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev))
+ return;
+ printf("%s:", ctl->info->id.name);
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %s", ev.value.integer.value[n] ? "ON" : "OFF");
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %ld", ev.value.integer.value[n]);
+ break;
+ }
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %lld", ev.value.integer64.value[n]);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ for (n = 0; n < ctl->info->count; n++) {
+ unsigned v = ev.value.enumerated.item[n];
+ printf(" %d (%s)", v,
+ (v < ctl->info->value.enumerated.items) ? ctl->ename[v] : "???");
+ }
+ break;
+ default:
+ printf(" ???");
+ }
+ printf("\n");
+}
+
+static long scale_int(struct snd_ctl_elem_info *ei, unsigned _percent)
+{
+ long percent;
+ long range;
+
+ if (_percent > 100)
+ percent = 100;
+ else
+ percent = (long) _percent;
+
+ range = (ei->value.integer.max - ei->value.integer.min);
+
+ return ei->value.integer.min + (range * percent) / 100LL;
+}
+
+static long long scale_int64(struct snd_ctl_elem_info *ei, unsigned _percent)
+{
+ long long percent;
+ long long range;
+
+ if (_percent > 100)
+ percent = 100;
+ else
+ percent = (long) _percent;
+
+ range = (ei->value.integer.max - ei->value.integer.min) * 100LL;
+
+ return ei->value.integer.min + (range / percent);
+}
+
+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent)
+{
+ struct snd_ctl_elem_value ev;
+ unsigned n;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer.value[n] = !!percent;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
+ long value = scale_int(ctl->info, percent);
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer.value[n] = value;
+ break;
+ }
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: {
+ long long value = scale_int64(ctl->info, percent);
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer64.value[n] = value;
+ break;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+}
+
+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value)
+{
+ unsigned n, max;
+ struct snd_ctl_elem_value ev;
+
+ if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ max = ctl->info->value.enumerated.items;
+ for (n = 0; n < max; n++) {
+ if (!strcmp(value, ctl->ename[n])) {
+ memset(&ev, 0, sizeof(ev));
+ ev.value.enumerated.item[0] = n;
+ ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev) < 0)
+ return -1;
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
diff --git a/libaudio2/alsa_pcm.c b/libaudio2/alsa_pcm.c
new file mode 100644
index 0000000..ad47b1a
--- /dev/null
+++ b/libaudio2/alsa_pcm.c
@@ -0,0 +1,390 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <linux/ioctl.h>
+
+#include "alsa_audio.h"
+
+#define __force
+#define __bitwise
+#define __user
+#include "asound.h"
+
+#define DEBUG 1
+
+/* alsa parameter manipulation cruft */
+
+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline int param_is_interval(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
+}
+
+static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ }
+}
+
+static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->max = val;
+ }
+}
+
+static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ i->max = val;
+ i->integer = 1;
+ }
+}
+
+static void param_init(struct snd_pcm_hw_params *p)
+{
+ int n;
+ memset(p, 0, sizeof(*p));
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = ~0;
+ m->bits[1] = ~0;
+ }
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = 0;
+ i->max = ~0;
+ }
+}
+
+/* debugging gunk */
+
+#if DEBUG
+static const char *param_name[PARAM_MAX+1] = {
+ [SNDRV_PCM_HW_PARAM_ACCESS] = "access",
+ [SNDRV_PCM_HW_PARAM_FORMAT] = "format",
+ [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat",
+
+ [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits",
+ [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits",
+ [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels",
+ [SNDRV_PCM_HW_PARAM_RATE] = "rate",
+ [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
+ [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
+ [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes",
+ [SNDRV_PCM_HW_PARAM_PERIODS] = "periods",
+ [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
+ [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
+ [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes",
+ [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time",
+};
+
+static void param_dump(struct snd_pcm_hw_params *p)
+{
+ int n;
+
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
+ struct snd_mask *m = param_to_mask(p, n);
+ printf("%s = %08x%08x\n", param_name[n],
+ m->bits[1], m->bits[0]);
+ }
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
+ struct snd_interval *i = param_to_interval(p, n);
+ printf("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n",
+ param_name[n], i->min, i->max, i->openmin,
+ i->openmax, i->integer, i->empty);
+ }
+ printf("info = %08x\n", p->info);
+ printf("msbits = %d\n", p->msbits);
+ printf("rate = %d/%d\n", p->rate_num, p->rate_den);
+ printf("fifo = %d\n", (int) p->fifo_size);
+}
+
+static void info_dump(struct snd_pcm_info *info)
+{
+ printf("device = %d\n", info->device);
+ printf("subdevice = %d\n", info->subdevice);
+ printf("stream = %d\n", info->stream);
+ printf("card = %d\n", info->card);
+ printf("id = '%s'\n", info->id);
+ printf("name = '%s'\n", info->name);
+ printf("subname = '%s'\n", info->subname);
+ printf("dev_class = %d\n", info->dev_class);
+ printf("dev_subclass = %d\n", info->dev_subclass);
+ printf("subdevices_count = %d\n", info->subdevices_count);
+ printf("subdevices_avail = %d\n", info->subdevices_avail);
+}
+#else
+static void param_dump(struct snd_pcm_hw_params *p) {}
+static void info_dump(struct snd_pcm_info *info) {}
+#endif
+
+#define PCM_ERROR_MAX 128
+
+struct pcm {
+ int fd;
+ unsigned flags;
+ int running:1;
+ int underruns;
+ unsigned buffer_size;
+ char error[PCM_ERROR_MAX];
+};
+
+unsigned pcm_buffer_size(struct pcm *pcm)
+{
+ return pcm->buffer_size;
+}
+
+const char* pcm_error(struct pcm *pcm)
+{
+ return pcm->error;
+}
+
+static int oops(struct pcm *pcm, int e, const char *fmt, ...)
+{
+ va_list ap;
+ int sz;
+
+ va_start(ap, fmt);
+ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
+ va_end(ap);
+ sz = strlen(pcm->error);
+
+ if (errno)
+ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
+ ": %s", strerror(e));
+ return -1;
+}
+
+int pcm_write(struct pcm *pcm, void *data, unsigned count)
+{
+ struct snd_xferi x;
+
+ if (pcm->flags & PCM_IN)
+ return -EINVAL;
+
+ x.buf = data;
+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
+
+ for (;;) {
+ if (!pcm->running) {
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
+ return oops(pcm, errno, "cannot prepare channel");
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
+ return oops(pcm, errno, "cannot write initial data");
+ fprintf(stderr,"RUNNING\n");
+ pcm->running = 1;
+ return 0;
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart */
+ pcm->underruns++;
+ continue;
+ }
+ return oops(pcm, errno, "cannot write stream data");
+ }
+ fprintf(stderr,".");
+ return 0;
+ }
+}
+
+int pcm_read(struct pcm *pcm, void *data, unsigned count)
+{
+ struct snd_xferi x;
+
+ if (!(pcm->flags & PCM_IN))
+ return -EINVAL;
+
+ x.buf = data;
+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
+
+ for (;;) {
+ if (!pcm->running) {
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
+ return oops(pcm, errno, "cannot prepare channel");
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START))
+ return oops(pcm, errno, "cannot start channel");
+ fprintf(stderr,"RUNNING\n");
+ pcm->running = 1;
+ return 0;
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart */
+ pcm->underruns++;
+ continue;
+ }
+ return oops(pcm, errno, "cannot read stream data");
+ }
+ fprintf(stderr,".");
+ return 0;
+ }
+}
+
+static struct pcm bad_pcm = {
+ .fd = -1,
+};
+
+int pcm_close(struct pcm *pcm)
+{
+ if (pcm == &bad_pcm)
+ return 0;
+
+ if (pcm->fd >= 0)
+ close(pcm->fd);
+ pcm->running = 0;
+ pcm->buffer_size = 0;
+ pcm->fd = -1;
+ return 0;
+}
+
+struct pcm *pcm_open(unsigned flags)
+{
+ const char *dname;
+ struct pcm *pcm;
+ struct snd_pcm_info info;
+ struct snd_pcm_hw_params params;
+ struct snd_pcm_sw_params sparams;
+ unsigned bufsz = 8192;
+
+ pcm = calloc(1, sizeof(struct pcm));
+ if (!pcm)
+ return &bad_pcm;
+
+ if (flags & PCM_IN) {
+ dname = "/dev/snd/pcmC0D0c";
+ } else {
+ dname = "/dev/snd/pcmC0D0p";
+ }
+
+ pcm->flags = flags;
+ pcm->fd = open(dname, O_RDWR);
+ if (pcm->fd < 0) {
+ oops(pcm, errno, "cannot open device '%s'");
+ return pcm;
+ }
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
+ oops(pcm, errno, "cannot get info - %s");
+ goto fail;
+ }
+ info_dump(&info);
+
+ param_init(&params);
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_ACCESS_RW_INTERLEAVED);
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FORMAT_S16_LE);
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
+ SNDRV_PCM_SUBFORMAT_STD);
+ param_set_min(&params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, bufsz);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
+ (flags & PCM_MONO) ? 16 : 32);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
+ (flags & PCM_MONO) ? 1 : 2);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, 2);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, 44100);
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
+ oops(pcm, errno, "cannot set hw params");
+ goto fail;
+ }
+ param_dump(&params);
+
+ memset(&sparams, 0, sizeof(sparams));
+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
+ sparams.period_step = 1;
+ sparams.avail_min = 1;
+ sparams.start_threshold = bufsz / 4;
+ sparams.stop_threshold = bufsz / 4;
+ sparams.xfer_align = bufsz / 8; /* needed for old kernels */
+ sparams.silence_size = 0;
+ sparams.silence_threshold = 0;
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
+ oops(pcm, errno, "cannot set sw params");
+ goto fail;
+ }
+
+ pcm->buffer_size = bufsz / 2;
+ pcm->underruns = 0;
+ return pcm;
+
+fail:
+ close(pcm->fd);
+ pcm->fd = -1;
+ return pcm;
+}
+
+int pcm_ready(struct pcm *pcm)
+{
+ return pcm->fd >= 0;
+}
diff --git a/libaudio2/amix.c b/libaudio2/amix.c
new file mode 100644
index 0000000..d978caa
--- /dev/null
+++ b/libaudio2/amix.c
@@ -0,0 +1,78 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "alsa_audio.h"
+
+
+struct mixer_ctl *get_ctl(struct mixer *mixer, char *name)
+{
+ char *p;
+ unsigned idx = 0;
+
+ if (isdigit(name[0]))
+ return mixer_get_nth_control(mixer, atoi(name) - 1);
+
+ p = strrchr(name, '#');
+ if (p) {
+ *p++ = 0;
+ idx = atoi(p);
+ }
+
+ return mixer_get_control(mixer, name, idx);
+}
+
+int main(int argc, char **argv)
+{
+ struct mixer *mixer;
+ struct mixer_ctl *ctl;
+ int r;
+
+ mixer = mixer_open();
+ if (!mixer)
+ return -1;
+
+ if (argc == 1) {
+ mixer_dump(mixer);
+ return 0;
+ }
+
+ ctl = get_ctl(mixer, argv[1]);
+ argc -= 2;
+ argv += 2;
+
+ if (!ctl) {
+ fprintf(stderr,"can't find control\n");
+ return -1;
+ }
+
+ if (argc) {
+ if (isdigit(argv[0][0]))
+ r = mixer_ctl_set(ctl, atoi(argv[0]));
+ else
+ r = mixer_ctl_select(ctl, argv[0]);
+ if (r)
+ fprintf(stderr,"oops: %s\n", strerror(errno));
+ } else {
+ mixer_ctl_print(ctl);
+ }
+ return 0;
+}
diff --git a/libaudio2/aplay.c b/libaudio2/aplay.c
new file mode 100644
index 0000000..5f28e32
--- /dev/null
+++ b/libaudio2/aplay.c
@@ -0,0 +1,140 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "alsa_audio.h"
+
+#define ID_RIFF 0x46464952
+#define ID_WAVE 0x45564157
+#define ID_FMT 0x20746d66
+#define ID_DATA 0x61746164
+
+#define FORMAT_PCM 1
+
+struct wav_header {
+ uint32_t riff_id;
+ uint32_t riff_sz;
+ uint32_t riff_fmt;
+ uint32_t fmt_id;
+ uint32_t fmt_sz;
+ uint16_t audio_format;
+ uint16_t num_channels;
+ uint32_t sample_rate;
+ uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
+ uint16_t block_align; /* num_channels * bps / 8 */
+ uint16_t bits_per_sample;
+ uint32_t data_id;
+ uint32_t data_sz;
+};
+
+int play_file(unsigned rate, unsigned channels, int fd, unsigned count)
+{
+ struct pcm *pcm;
+ struct mixer *mixer;
+ struct pcm_ctl *ctl = NULL;
+ unsigned bufsize;
+ char *data;
+ unsigned flags = PCM_OUT;
+
+ if (channels == 1)
+ flags |= PCM_MONO;
+ else
+ flags |= PCM_STEREO;
+
+ pcm = pcm_open(flags);
+ if (!pcm_ready(pcm)) {
+ pcm_close(pcm);
+ return -1;
+ }
+
+ mixer = mixer_open();
+ if (mixer)
+ ctl = mixer_get_control(mixer,"Playback Path", 0);
+
+ bufsize = pcm_buffer_size(pcm);
+ data = malloc(bufsize);
+ if (!data) {
+ fprintf(stderr,"could not allocate %d bytes\n", count);
+ return -1;
+ }
+
+ while (read(fd, data, bufsize) == bufsize) {
+ if (pcm_write(pcm, data, bufsize))
+ break;
+
+ /* HACK: remove */
+ if (ctl) {
+ mixer_ctl_select(ctl, "SPK");
+ ctl = 0;
+ }
+ }
+ pcm_close(pcm);
+ return 0;
+}
+
+int play_wav(const char *fn)
+{
+ struct wav_header hdr;
+ unsigned rate, channels;
+ int fd;
+ fd = open(fn, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "aplay: cannot open '%s'\n", fn);
+ return -1;
+ }
+ if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ fprintf(stderr, "aplay: cannot read header\n");
+ return -1;
+ }
+ fprintf(stderr,"aplay: %d ch, %d hz, %d bit, %s\n",
+ hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
+ hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
+
+ if ((hdr.riff_id != ID_RIFF) ||
+ (hdr.riff_fmt != ID_WAVE) ||
+ (hdr.fmt_id != ID_FMT)) {
+ fprintf(stderr, "aplay: '%s' is not a riff/wave file\n", fn);
+ return -1;
+ }
+ if ((hdr.audio_format != FORMAT_PCM) ||
+ (hdr.fmt_sz != 16)) {
+ fprintf(stderr, "aplay: '%s' is not pcm format\n", fn);
+ return -1;
+ }
+ if (hdr.bits_per_sample != 16) {
+ fprintf(stderr, "aplay: '%s' is not 16bit per sample\n", fn);
+ return -1;
+ }
+
+ return play_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr,"usage: aplay <file>\n");
+ return -1;
+ }
+
+ return play_wav(argv[1]);
+}
+
diff --git a/libaudio2/arec.c b/libaudio2/arec.c
new file mode 100644
index 0000000..b1e9eda
--- /dev/null
+++ b/libaudio2/arec.c
@@ -0,0 +1,128 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "alsa_audio.h"
+
+#define ID_RIFF 0x46464952
+#define ID_WAVE 0x45564157
+#define ID_FMT 0x20746d66
+#define ID_DATA 0x61746164
+
+#define FORMAT_PCM 1
+
+struct wav_header {
+ uint32_t riff_id;
+ uint32_t riff_sz;
+ uint32_t riff_fmt;
+ uint32_t fmt_id;
+ uint32_t fmt_sz;
+ uint16_t audio_format;
+ uint16_t num_channels;
+ uint32_t sample_rate;
+ uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
+ uint16_t block_align; /* num_channels * bps / 8 */
+ uint16_t bits_per_sample;
+ uint32_t data_id;
+ uint32_t data_sz;
+};
+
+int record_file(unsigned rate, unsigned channels, int fd, unsigned count)
+{
+ struct pcm *pcm;
+ unsigned avail, xfer, bufsize;
+ char *data, *next;
+ int r;
+
+ pcm = pcm_open(PCM_IN|PCM_MONO);
+ if (!pcm_ready(pcm)) {
+ pcm_close(pcm);
+ goto fail;
+ }
+
+ bufsize = pcm_buffer_size(pcm);
+
+ data = malloc(bufsize);
+ if (!data) {
+ fprintf(stderr,"could not allocate %d bytes\n", count);
+ return -1;
+ }
+
+ while (!pcm_read(pcm, data, bufsize)) {
+ if (write(fd, data, bufsize) != bufsize) {
+ fprintf(stderr,"could not write %d bytes\n", bufsize);
+ return -1;
+ }
+ }
+
+ close(fd);
+ pcm_close(pcm);
+ return 0;
+
+fail:
+ fprintf(stderr,"pcm error: %s\n", pcm_error(pcm));
+ return -1;
+}
+
+int rec_wav(const char *fn)
+{
+ struct wav_header hdr;
+ unsigned rate, channels;
+ int fd;
+ fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+ if (fd < 0) {
+ fprintf(stderr, "arec: cannot open '%s'\n", fn);
+ return -1;
+ }
+
+ hdr.riff_id = ID_RIFF;
+ hdr.riff_fmt = ID_WAVE;
+ hdr.fmt_id = ID_FMT;
+ hdr.audio_format = FORMAT_PCM;
+ hdr.fmt_sz = 16;
+ hdr.bits_per_sample = 16;
+ hdr.num_channels = 1;
+ hdr.data_sz = 0;
+ hdr.sample_rate = 44100;
+
+ if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ fprintf(stderr, "arec: cannot write header\n");
+ return -1;
+ }
+ fprintf(stderr,"arec: %d ch, %d hz, %d bit, %s\n",
+ hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
+ hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
+
+
+ return record_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr,"usage: arec <file>\n");
+ return -1;
+ }
+
+ return rec_wav(argv[1]);
+}
+
diff --git a/libaudio2/asound.h b/libaudio2/asound.h
new file mode 100644
index 0000000..6a17f29
--- /dev/null
+++ b/libaudio2/asound.h
@@ -0,0 +1,814 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __SOUND_ASOUND_H
+#define __SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#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)))
+
+struct snd_aes_iec958 {
+ unsigned char status[24];
+ unsigned char subcode[147];
+ unsigned char pad;
+ unsigned char dig_subframe[4];
+};
+
+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+ SNDRV_HWDEP_IFACE_OPL2 = 0,
+ SNDRV_HWDEP_IFACE_OPL3,
+ SNDRV_HWDEP_IFACE_OPL4,
+ SNDRV_HWDEP_IFACE_SB16CSP,
+ SNDRV_HWDEP_IFACE_EMU10K1,
+ SNDRV_HWDEP_IFACE_YSS225,
+ SNDRV_HWDEP_IFACE_ICS2115,
+ SNDRV_HWDEP_IFACE_SSCAPE,
+ SNDRV_HWDEP_IFACE_VX,
+ SNDRV_HWDEP_IFACE_MIXART,
+ SNDRV_HWDEP_IFACE_USX2Y,
+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
+ SNDRV_HWDEP_IFACE_BLUETOOTH,
+ SNDRV_HWDEP_IFACE_USX2Y_PCM,
+ SNDRV_HWDEP_IFACE_PCXHR,
+ SNDRV_HWDEP_IFACE_SB_RC,
+ SNDRV_HWDEP_IFACE_HDA,
+ SNDRV_HWDEP_IFACE_USB_STREAM,
+
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+ unsigned int device;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ int iface;
+ unsigned char reserved[64];
+};
+
+struct snd_hwdep_dsp_status {
+ unsigned int version;
+ unsigned char id[32];
+ unsigned int num_dsps;
+ unsigned int dsp_loaded;
+ unsigned int chip_ready;
+ unsigned char reserved[16];
+};
+
+struct snd_hwdep_dsp_image {
+ unsigned int index;
+ unsigned char name[64];
+ unsigned char __user *image;
+ size_t length;
+ unsigned long driver_data;
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+ SNDRV_PCM_CLASS_GENERIC = 0,
+ SNDRV_PCM_CLASS_MULTI,
+ SNDRV_PCM_CLASS_MODEM,
+ SNDRV_PCM_CLASS_DIGITIZER,
+
+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
+ SNDRV_PCM_SUBCLASS_MULTI_MIX,
+
+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+ SNDRV_PCM_STREAM_PLAYBACK = 0,
+ SNDRV_PCM_STREAM_CAPTURE,
+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP 0x00000001
+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
+#define SNDRV_PCM_INFO_DOUBLE 0x00000004
+#define SNDRV_PCM_INFO_BATCH 0x00000010
+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
+#define SNDRV_PCM_INFO_COMPLEX 0x00000400
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
+#define SNDRV_PCM_INFO_RESUME 0x00040000
+#define SNDRV_PCM_INFO_PAUSE 0x00080000
+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
+#define SNDRV_PCM_INFO_SYNC_START 0x00400000
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
+
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+ unsigned char id[16];
+ unsigned short id16[8];
+ unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ int dev_class;
+ int dev_subclass;
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ union snd_pcm_sync_id sync;
+ unsigned char reserved[64];
+};
+
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0
+#define SNDRV_PCM_HW_PARAM_FORMAT 1
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10
+#define SNDRV_PCM_HW_PARAM_RATE 11
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
+#define SNDRV_PCM_HW_PARAM_PERIODS 15
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
+
+struct snd_interval {
+ unsigned int min, max;
+ unsigned int openmin:1,
+ openmax:1,
+ integer:1,
+ empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+ unsigned int flags;
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+ struct snd_mask mres[5];
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9];
+ unsigned int rmask;
+ unsigned int cmask;
+ unsigned int info;
+ unsigned int msbits;
+ unsigned int rate_num;
+ unsigned int rate_den;
+ snd_pcm_uframes_t fifo_size;
+ unsigned char reserved[64];
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_NONE = 0,
+ SNDRV_PCM_TSTAMP_ENABLE,
+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+ int tstamp_mode;
+ unsigned int period_step;
+ unsigned int sleep_min;
+ snd_pcm_uframes_t avail_min;
+ snd_pcm_uframes_t xfer_align;
+ snd_pcm_uframes_t start_threshold;
+ snd_pcm_uframes_t stop_threshold;
+ snd_pcm_uframes_t silence_threshold;
+ snd_pcm_uframes_t silence_size;
+ snd_pcm_uframes_t boundary;
+ unsigned char reserved[64];
+};
+
+struct snd_pcm_channel_info {
+ unsigned int channel;
+ __kernel_off_t offset;
+ unsigned int first;
+ unsigned int step;
+};
+
+struct snd_pcm_status {
+ snd_pcm_state_t state;
+ struct timespec trigger_tstamp;
+ struct timespec tstamp;
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t hw_ptr;
+ snd_pcm_sframes_t delay;
+ snd_pcm_uframes_t avail;
+ snd_pcm_uframes_t avail_max;
+ snd_pcm_uframes_t overrange;
+ snd_pcm_state_t suspended_state;
+ unsigned char reserved[60];
+};
+
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state;
+ int pad1;
+ snd_pcm_uframes_t hw_ptr;
+ struct timespec tstamp;
+ snd_pcm_state_t suspended_state;
+};
+
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t avail_min;
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
+
+struct snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+ struct snd_pcm_mmap_status status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control control;
+ unsigned char reserved[64];
+ } c;
+};
+
+struct snd_xferi {
+ snd_pcm_sframes_t result;
+ void __user *buf;
+ snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+ snd_pcm_sframes_t result;
+ void __user * __user *bufs;
+ snd_pcm_uframes_t frames;
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
+
+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
+
+struct snd_rawmidi_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned int flags;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ unsigned char reserved[64];
+};
+
+struct snd_rawmidi_params {
+ int stream;
+ size_t buffer_size;
+ size_t avail_min;
+ unsigned int no_active_sensing: 1;
+ unsigned char reserved[16];
+};
+
+struct snd_rawmidi_status {
+ int stream;
+ struct timespec tstamp;
+ size_t avail;
+ size_t xruns;
+ unsigned char reserved[16];
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
+
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+ SNDRV_TIMER_CLASS_NONE = -1,
+ SNDRV_TIMER_CLASS_SLAVE = 0,
+ SNDRV_TIMER_CLASS_GLOBAL,
+ SNDRV_TIMER_CLASS_CARD,
+ SNDRV_TIMER_CLASS_PCM,
+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+enum {
+ SNDRV_TIMER_SCLASS_NONE = 0,
+ SNDRV_TIMER_SCLASS_APPLICATION,
+ SNDRV_TIMER_SCLASS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
+#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
+
+#define SNDRV_TIMER_FLG_SLAVE (1<<0)
+
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
+ int card;
+ int device;
+ int subdevice;
+};
+
+struct snd_timer_ginfo {
+ struct snd_timer_id tid;
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned long resolution_min;
+ unsigned long resolution_max;
+ unsigned int clients;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+ struct snd_timer_id tid;
+ unsigned long period_num;
+ unsigned long period_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+ struct snd_timer_id tid;
+ unsigned long resolution;
+ unsigned long resolution_num;
+ unsigned long resolution_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+ struct snd_timer_id id;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_info {
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
+
+struct snd_timer_params {
+ unsigned int flags;
+ unsigned int ticks;
+ unsigned int queue_size;
+ unsigned int reserved0;
+ unsigned int filter;
+ unsigned char reserved[60];
+};
+
+struct snd_timer_status {
+ struct timespec tstamp;
+ unsigned int resolution;
+ unsigned int lost;
+ unsigned int overrun;
+ unsigned int queue;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
+
+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
+
+struct snd_timer_read {
+ unsigned int resolution;
+ unsigned int ticks;
+};
+
+enum {
+ SNDRV_TIMER_EVENT_RESOLUTION = 0,
+ SNDRV_TIMER_EVENT_TICK,
+ SNDRV_TIMER_EVENT_START,
+ SNDRV_TIMER_EVENT_STOP,
+ SNDRV_TIMER_EVENT_CONTINUE,
+ SNDRV_TIMER_EVENT_PAUSE,
+ SNDRV_TIMER_EVENT_EARLY,
+ SNDRV_TIMER_EVENT_SUSPEND,
+ SNDRV_TIMER_EVENT_RESUME,
+
+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+ int event;
+ struct timespec tstamp;
+ unsigned int val;
+};
+
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+struct snd_ctl_card_info {
+ int card;
+ int pad;
+ unsigned char id[16];
+ unsigned char driver[16];
+ unsigned char name[32];
+ unsigned char longname[80];
+ unsigned char reserved_[16];
+ unsigned char mixername[80];
+ unsigned char components[128];
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
+
+#define SNDRV_CTL_POWER_D0 0x0000
+#define SNDRV_CTL_POWER_D1 0x0100
+#define SNDRV_CTL_POWER_D2 0x0200
+#define SNDRV_CTL_POWER_D3 0x0300
+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
+
+struct snd_ctl_elem_id {
+ unsigned int numid;
+ snd_ctl_elem_iface_t iface;
+ unsigned int device;
+ unsigned int subdevice;
+ unsigned char name[44];
+ unsigned int index;
+};
+
+struct snd_ctl_elem_list {
+ unsigned int offset;
+ unsigned int space;
+ unsigned int used;
+ unsigned int count;
+ struct snd_ctl_elem_id __user *pids;
+ unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id;
+ snd_ctl_elem_type_t type;
+ unsigned int access;
+ unsigned int count;
+ __kernel_pid_t owner;
+ union {
+ struct {
+ long min;
+ long max;
+ long step;
+ } integer;
+ struct {
+ long long min;
+ long long max;
+ long long step;
+ } integer64;
+ struct {
+ unsigned int items;
+ unsigned int item;
+ char name[64];
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ union {
+ unsigned short d[4];
+ unsigned short *d_ptr;
+ } dimen;
+ unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id;
+ unsigned int indirect: 1;
+ union {
+ union {
+ long value[128];
+ long *value_ptr;
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr;
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr;
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr;
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value;
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+ unsigned int numid;
+ unsigned int length;
+ unsigned int tlv[0];
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
+
+enum sndrv_ctl_event_type {
+ SNDRV_CTL_EVENT_ELEM = 0,
+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
+
+struct snd_ctl_event {
+ int type;
+ union {
+ struct {
+ unsigned int mask;
+ struct snd_ctl_elem_id id;
+ } elem;
+ unsigned char data8[60];
+ } data;
+};
+
+#define SNDRV_CTL_NAME_NONE ""
+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
+#define SNDRV_CTL_NAME_CAPTURE "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif
+