├── Android.mk ├── alsa.mk ├── alsa_audio.h ├── AudioHardware.h ├── alsa_mixer.c ├── alsa_pcm.c ├── asound.h └── AudioHardware.cpp /Android.mk: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011 The Android-x86 Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # 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 46 | -------------------------------------------------------------------------------- /alsa.mk: -------------------------------------------------------------------------------- 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 \ 54 | -------------------------------------------------------------------------------- /alsa_audio.h: -------------------------------------------------------------------------------- 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 86 | -------------------------------------------------------------------------------- /AudioHardware.h: -------------------------------------------------------------------------------- 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 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include 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 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 output() { return mOutput; } 132 | 133 | protected: 134 | virtual status_t dump(int fd, const Vector& args); 135 | 136 | private: 137 | 138 | bool mInit; 139 | bool mMicMute; 140 | sp mOutput; 141 | SortedVector < sp > 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& 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& 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 332 | -------------------------------------------------------------------------------- /alsa_mixer.c: -------------------------------------------------------------------------------- 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 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 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 | } 372 | -------------------------------------------------------------------------------- /alsa_pcm.c: -------------------------------------------------------------------------------- 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 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 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(¶ms); 355 | param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, 356 | SNDRV_PCM_ACCESS_RW_INTERLEAVED); 357 | param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, 358 | SNDRV_PCM_FORMAT_S16_LE); 359 | param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT, 360 | SNDRV_PCM_SUBFORMAT_STD); 361 | param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz); 362 | param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16); 363 | param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS, 364 | (flags & PCM_MONO) ? 16 : 32); 365 | param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, 366 | (flags & PCM_MONO) ? 1 : 2); 367 | param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt); 368 | param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, 44100); 369 | 370 | if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) { 371 | oops(pcm, errno, "cannot set hw params"); 372 | goto fail; 373 | } 374 | param_dump(¶ms); 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 | } 405 | -------------------------------------------------------------------------------- /asound.h: -------------------------------------------------------------------------------- 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 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 814 | -------------------------------------------------------------------------------- /AudioHardware.cpp: -------------------------------------------------------------------------------- 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 18 | 19 | //#define LOG_NDEBUG 0 20 | 21 | #define LOG_TAG "AudioHardware" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "AudioHardware.h" 36 | #include 37 | #include 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 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 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 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 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 spOut; 230 | sp 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 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& 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::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(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 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& 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 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& 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 1812 | --------------------------------------------------------------------------------