audio_hal.c revision eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1
119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/* 219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * Copyright (C) 2012 The Android Open Source Project 319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * 419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * you may not use this file except in compliance with the License. 619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * You may obtain a copy of the License at 719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * 819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * http://www.apache.org/licenses/LICENSE-2.0 919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * 1019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * Unless required by applicable law or agreed to in writing, software 1119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * distributed under the License is distributed on an "AS IS" BASIS, 1219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * See the License for the specific language governing permissions and 1419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * limitations under the License. 1519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson */ 1619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 1719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#define LOG_TAG "usb_audio_hw" 1819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/*#define LOG_NDEBUG 0*/ 1919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 2019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <errno.h> 2119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <pthread.h> 2219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <stdint.h> 2319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <sys/time.h> 2419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <stdlib.h> 2519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 2619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <cutils/log.h> 2719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <cutils/str_parms.h> 2819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <cutils/properties.h> 2919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 3019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <hardware/hardware.h> 3119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <system/audio.h> 3219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <hardware/audio.h> 3319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 3419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson#include <tinyalsa/asoundlib.h> 3519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 36eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* This is the default configuration to hand to The Framework on the initial 37eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * adev_open_output_stream(). Actual device attributes will be used on the subsequent 38eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * adev_open_output_stream() after the card and device number have been set in out_set_parameters() 39eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 40eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define OUT_PERIOD_SIZE 1024 41eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define OUT_PERIOD_COUNT 4 42eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define OUT_SAMPLING_RATE 44100 43eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 44eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstruct pcm_config default_alsa_out_config = { 4519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .channels = 2, 46eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .rate = OUT_SAMPLING_RATE, 47eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .period_size = OUT_PERIOD_SIZE, 48eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .period_count = OUT_PERIOD_COUNT, 4919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .format = PCM_FORMAT_S16_LE, 5019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 5119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 52eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 53eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Input defaults. See comment above. 54eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 55eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define IN_PERIOD_SIZE 1024 56eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define IN_PERIOD_COUNT 4 57eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean#define IN_SAMPLING_RATE 44100 58eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 59eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstruct pcm_config default_alsa_in_config = { 60eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .channels = 2, 61eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .rate = IN_SAMPLING_RATE, 62eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .period_size = IN_PERIOD_SIZE, 63eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .period_count = IN_PERIOD_COUNT, 64eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .format = PCM_FORMAT_S16_LE, 65eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .start_threshold = 1, 66eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean .stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT), 67eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean}; 68eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 6919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct audio_device { 7019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_hw_device hw_device; 7119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 7219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_t lock; /* see note below on mutex acquisition order */ 73eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 74eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* output */ 75eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int out_card; 76eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int out_device; 77eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 78eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* input */ 79eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int in_card; 80eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int in_device; 81eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 8219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson bool standby; 8319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 8419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 8519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct stream_out { 8619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out stream; 8719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 88eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean pthread_mutex_t lock; /* see note below on mutex acquisition order */ 89eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct pcm *pcm; /* state of the stream */ 90eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean bool standby; 91eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 92eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *dev; /* hardware information */ 93eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 94eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean void * conversion_buffer; /* any conversions are put into here 95eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * they could come from here too if 96eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * there was a previous conversion */ 97eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t conversion_buffer_size; /* in bytes */ 98eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean}; 99eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 100eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 101eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Output Configuration Cache 102eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * FIXME(pmclean) This is not rentrant. Should probably be moved into the stream structure 103eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * but that will involve changes in The Framework. 104eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 105eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic struct pcm_config cached_output_hardware_config; 106eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic bool output_hardware_config_is_cached = false; 107eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 108eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstruct stream_in { 109eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_stream_in stream; 110eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 11119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_t lock; /* see note below on mutex acquisition order */ 11219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct pcm *pcm; 11319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson bool standby; 11419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 115eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct pcm_config alsa_pcm_config; 116eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 11719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *dev; 118eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 119eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_config hal_pcm_config; 120eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 121eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned int requested_rate; 122eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean// struct resampler_itfe *resampler; 123eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean// struct resampler_buffer_provider buf_provider; 124eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int16_t *buffer; 125eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t buffer_size; 126eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t frames_in; 127eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int read_status; 12819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 12919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 130eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 131eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Utility 132eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 133eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 134eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Translates from ALSA format ID to ANDROID_AUDIO_CORE format ID 135eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * (see master/system/core/include/core/audio.h) 136eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * TODO(pmclean) Replace with audio_format_from_pcm_format() (in hardware/audio_alsaops.h). 137eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * post-integration. 13819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson */ 139eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic audio_format_t alsa_to_fw_format_id(int alsa_fmt_id) 140eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 141eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean switch (alsa_fmt_id) { 142eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S8: 143eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return AUDIO_FORMAT_PCM_8_BIT; 14419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 145eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S24_3LE: 146eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) make sure this is the 'right' sort of 24-bit 147eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return AUDIO_FORMAT_PCM_8_24_BIT; 14819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 149eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S32_LE: 150eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S24_LE: 151eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return AUDIO_FORMAT_PCM_32_BIT; 152eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 153eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 154eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return AUDIO_FORMAT_PCM_16_BIT; 155eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 156eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 157eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 158eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Data Conversions 159eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 160eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 161eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Convert a buffer of PCM16LE samples to packed (3-byte) PCM24LE samples. 162eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * in_buff points to the buffer of PCM16 samples 163eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * num_in_samples size of input buffer in SAMPLES 164eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * out_buff points to the buffer to receive converted PCM24 LE samples. 165eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * returns the number of BYTES of output data. 166eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * We are doing this since we *always* present to The Framework as A PCM16LE device, but need to 167eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * support PCM24_3LE (24-bit, packed). 168eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * NOTE: we're just filling the low-order byte of the PCM24LE samples with 0. 169eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * TODO(pmclean, hung) Move this to a utilities module. 170eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 171eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic size_t convert_16_to_24_3(unsigned short * in_buff, 172eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t num_in_samples, 173eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned char * out_buff) { 174eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* 175eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Move from back to front so that the conversion can be done in-place 176eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * i.e. in_buff == out_buff 177eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 178eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int in_buff_size_in_bytes = num_in_samples * 2; 179eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* we need 3 bytes in the output for every 2 bytes in the input */ 180eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int out_buff_size_in_bytes = ((3 * in_buff_size_in_bytes) / 2); 181eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned char* dst_ptr = out_buff + out_buff_size_in_bytes - 1; 182eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int src_smpl_index; 183eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned char* src_ptr = ((unsigned char *)in_buff) + in_buff_size_in_bytes - 1; 184eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean for (src_smpl_index = 0; src_smpl_index < num_in_samples; src_smpl_index++) { 185eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = *src_ptr--; /* hi-byte */ 186eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = *src_ptr--; /* low-byte */ 187eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = 0; /* zero-byte */ 188eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 189eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 190eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* return number of *bytes* generated */ 191eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return out_buff_size_in_bytes; 192eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 193eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 194eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 195eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Convert a buffer of 2-channel PCM16 samples to 4-channel PCM16 channels 196eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * in_buff points to the buffer of PCM16 samples 197eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * num_in_samples size of input buffer in SAMPLES 198eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * out_buff points to the buffer to receive converted PCM16 samples. 199eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * returns the number of BYTES of output data. 200eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * NOTE channels 3 & 4 are filled with silence. 201eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * We are doing this since we *always* present to The Framework as STEREO device, but need to 202eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * support 4-channel devices. 203eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * TODO(pmclean, hung) Move this to a utilities module. 204eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 205eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic size_t convert_2chan16_to_4chan16(unsigned short* in_buff, 206eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t num_in_samples, 207eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned short* out_buff) { 208eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* 209eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Move from back to front so that the conversion can be done in-place 210eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * i.e. in_buff == out_buff 211eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 212eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int out_buff_size = num_in_samples * 2; 213eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned short* dst_ptr = out_buff + out_buff_size - 1; 214eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int src_index; 215eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned short* src_ptr = in_buff + num_in_samples - 1; 216eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean for (src_index = 0; src_index < num_in_samples; src_index += 2) { 217eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = 0; /* chan 4 */ 218eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = 0; /* chan 3 */ 219eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = *src_ptr--; /* chan 2 */ 220eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *dst_ptr-- = *src_ptr--; /* chan 1 */ 221eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 222eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 223eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* return number of *bytes* generated */ 224eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return out_buff_size * 2; 225eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 226eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 227eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 228eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * ALSA Utilities 229eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 230eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 231eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * gets the ALSA bit-format flag from a bits-per-sample value. 232eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * TODO(pmclean, hung) Move this to a utilities module. 233eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 234eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int bits_to_alsa_format(int bits_per_sample, int default_format) 23519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 236eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean enum pcm_format format; 237eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean for (format = PCM_FORMAT_S16_LE; format < PCM_FORMAT_MAX; format++) { 238eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (pcm_format_to_bits(format) == bits_per_sample) { 239eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return format; 240eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 241eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 242eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return default_format; 243eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 24419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 245eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 246eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Reads and decodes configuration info from the specified ALSA card/device 247eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 248eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int read_alsa_device_config(int card, int device, int io_type, struct pcm_config * config) 249eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 250eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw - read_alsa_device_config(card:%d device:%d)", card, device); 25119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 252eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (card < 0 || device < 0) { 253eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -EINVAL; 254eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 25519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 256eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct pcm_params * alsa_hw_params = pcm_params_get(card, device, io_type); 257eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (alsa_hw_params == NULL) { 258eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -EINVAL; 25919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 26019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 261eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* 262eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * This Logging will be useful when testing new USB devices. 263eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 264eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_SAMPLE_BITS min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS), pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS)); */ 265eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_FRAME_BITS min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_FRAME_BITS), pcm_params_get_max(alsa_hw_params, PCM_PARAM_FRAME_BITS)); */ 266eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_CHANNELS min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS), pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS)); */ 267eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_RATE min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE), pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE)); */ 268eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_TIME min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_TIME), pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_TIME)); */ 269eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_SIZE min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE), pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE)); */ 270eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_BYTES min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_BYTES), pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_BYTES)); */ 271eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_PERIODS min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS), pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS)); */ 272eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_TIME min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_TIME), pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_TIME)); */ 273eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_SIZE min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE), pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_SIZE)); */ 274eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_BYTES min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_BYTES), pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_BYTES)); */ 275eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* ALOGV("usb:audio_hw - PCM_PARAM_TICK_TIME min:%d, max:%d", pcm_params_get_min(alsa_hw_params, PCM_PARAM_TICK_TIME), pcm_params_get_max(alsa_hw_params, PCM_PARAM_TICK_TIME)); */ 276eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 277eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS); 278eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE); 279eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS); 280eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS); 281eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 282eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int bits_per_sample = pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS); 283eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->format = bits_to_alsa_format(bits_per_sample, PCM_FORMAT_S16_LE); 284eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 28519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 28619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 28719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 288eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* 289eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * HAl Functions 290eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 291eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/** 292eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * NOTE: when multiple mutexes have to be acquired, always respect the 293eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * following order: hw device > out stream 294eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 29519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 296eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* Helper functions */ 29719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_sample_rate(const struct audio_stream *stream) 29819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 299eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return cached_output_hardware_config.rate; 30019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 30119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 30219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 30319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 30419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 30519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 30619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 30719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic size_t out_get_buffer_size(const struct audio_stream *stream) 30819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 309eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return cached_output_hardware_config.period_size * audio_stream_frame_size(stream); 31019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 31119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 31219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_channels(const struct audio_stream *stream) 31319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 314eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Always Stero for now. We will do *some* conversions in this HAL. 315eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // TODO(pmclean) When AudioPolicyManager & AudioFlinger supports arbitrary channels 316eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // rewrite this to return the ACTUAL channel format 31719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return AUDIO_CHANNEL_OUT_STEREO; 31819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 31919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 32019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic audio_format_t out_get_format(const struct audio_stream *stream) 32119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 322eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Always return 16-bit PCM. We will do *some* conversions in this HAL. 323eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // TODO(pmclean) When AudioPolicyManager & AudioFlinger supports arbitrary PCM formats 324eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // rewrite this to return the ACTUAL data format 32519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return AUDIO_FORMAT_PCM_16_BIT; 32619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 32719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 32819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_format(struct audio_stream *stream, audio_format_t format) 32919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 33019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 33119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 33219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 33319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_standby(struct audio_stream *stream) 33419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 33519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 33619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 33719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->dev->lock); 33819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->lock); 33919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 34019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!out->standby) { 34119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pcm_close(out->pcm); 34219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->pcm = NULL; 34319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->standby = true; 34419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 34519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 34619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 34719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->dev->lock); 34819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 34919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 35019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 35119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 35219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_dump(const struct audio_stream *stream, int fd) 35319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 35419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 35519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 35619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 35719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 35819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 359eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::out out_set_parameters() keys:%s", kvpairs); 360eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 36119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 36219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = out->dev; 36319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct str_parms *parms; 36419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson char value[32]; 365eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int param_val; 36619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int routing = 0; 367eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int ret_value = 0; 36819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 36919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson parms = str_parms_create_str(kvpairs); 37019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&adev->lock); 37119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 372eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean bool recache_device_params = false; 373eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean param_val = str_parms_get_str(parms, "card", value, sizeof(value)); 374eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (param_val >= 0) { 375eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean adev->out_card = atoi(value); 376eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean recache_device_params = true; 377eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 378eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 379eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean param_val = str_parms_get_str(parms, "device", value, sizeof(value)); 380eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (param_val >= 0) { 381eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean adev->out_device = atoi(value); 382eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean recache_device_params = true; 383eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 38419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 385eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (recache_device_params && adev->out_card >= 0 && adev->out_device >= 0) { 386eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ret_value = read_alsa_device_config(adev->out_card, adev->out_device, PCM_OUT, 387eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean &(cached_output_hardware_config)); 388eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean output_hardware_config_is_cached = (ret_value == 0); 389eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 39019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 39119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&adev->lock); 39219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson str_parms_destroy(parms); 39319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 394eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return ret_value; 39519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 39619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 397eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean//TODO(pmclean) it seems like both out_get_parameters() and in_get_parameters() 398eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean// could be written in terms of a get_device_parameters(io_type) 399eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 400eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic char * out_get_parameters(const struct audio_stream *stream, const char *keys) { 401eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_out *out = (struct stream_out *) stream; 402eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = out->dev; 403eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 404eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned min, max; 405eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 406eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct str_parms *query = str_parms_create_str(keys); 407eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct str_parms *result = str_parms_create(); 408eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 409eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int num_written = 0; 410eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean char buffer[256]; 411eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int buffer_size = sizeof(buffer) / sizeof(buffer[0]); 412eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean char* result_str = NULL; 413eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 414eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct pcm_params * alsa_hw_params = pcm_params_get(adev->out_card, adev->out_device, PCM_OUT); 415eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 416eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // These keys are from hardware/libhardware/include/audio.h 417eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported sample rates 418eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { 419eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // pcm_hw_params doesn't have a list of supported samples rates, just a min and a max, so 420eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // if they are different, return a list containing those two values, otherwise just the one. 421eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE); 422eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE); 423eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 424eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 425eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", 426eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max); 427eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 428eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, 429eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean buffer); 430eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES 431eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 432eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported channel counts 433eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { 434eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Similarly for output channels count 435eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS); 436eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS); 437eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 438eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 439eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", max); 440eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 441eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, buffer); 442eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_CHANNELS 443eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 444eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported sample formats 445eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { 446eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Similarly for output channels count 447eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean): this is wrong. 448eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS); 449eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS); 450eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 451eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 452eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", max); 453eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 454eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, buffer); 455eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_FORMATS 456eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 457eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean result_str = str_parms_to_str(result); 458eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 459eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // done with these... 460eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_destroy(query); 461eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_destroy(result); 462eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 463eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return result_str; 46419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 46519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 46619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_latency(const struct audio_stream_out *stream) 46719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 468eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_out *out = (struct stream_out *)stream; 469eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 470eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean): Do we need a term here for the USB latency 471eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // (as reported in the USB descriptors)? 472eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean uint32_t latency = (cached_output_hardware_config.period_size * 473eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean cached_output_hardware_config.period_count * 1000) / out_get_sample_rate(&stream->common); 474eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return latency; 47519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 47619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 47719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_volume(struct audio_stream_out *stream, float left, 47819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson float right) 47919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 48019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 48119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 48219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 483eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* must be called with hw device and output stream mutexes locked */ 484eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int start_output_stream(struct stream_out *out) 485eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 486eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = out->dev; 487eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int return_val = 0; 488eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 489eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::out start_output_stream(card:%d device:%d)", 490eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean adev->out_card, adev->out_device); 491eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 492eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->pcm = pcm_open(adev->out_card, adev->out_device, PCM_OUT, &cached_output_hardware_config); 493eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (out->pcm == NULL) { 494eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOMEM; 495eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 496eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 497eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (out->pcm && !pcm_is_ready(out->pcm)) { 498eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGE("audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(out->pcm)); 499eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean pcm_close(out->pcm); 500eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOMEM; 501eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 502eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 503eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Setup conversion buffer 504eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t buffer_size = out_get_buffer_size(&(out->stream.common)); 505eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 506eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // computer maximum potential buffer size. 507eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // * 2 for stereo -> quad conversion 508eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // * 3/2 for 16bit -> 24 bit conversion 509eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) - remove this when AudioPolicyManger/AudioFlinger support arbitrary formats 510eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // (and do these conversions themselves) 511eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer_size = (buffer_size * 3 * 2) / 2; 512eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer = realloc(out->conversion_buffer, out->conversion_buffer_size); 513eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 514eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 515eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 516eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 517eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) 51819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 51919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int ret; 52019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 52119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 52219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->dev->lock); 52319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->lock); 52419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (out->standby) { 52519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson ret = start_output_stream(out); 52619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret != 0) { 52719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson goto err; 52819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 52919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->standby = false; 53019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 53119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 532eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean void * write_buff = buffer; 533eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int num_write_buff_bytes = bytes; 534eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 535eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* 536eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * Num Channels conversion 537eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 538eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int num_device_channels = cached_output_hardware_config.channels; 539eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int num_req_channels = 2; /* always, for now */ 540eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (num_device_channels != num_req_channels && num_device_channels == 4) { 541eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_write_buff_bytes = 542eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean convert_2chan16_to_4chan16(write_buff, num_write_buff_bytes / 2, 543eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer); 544eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean write_buff = out->conversion_buffer; 545eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 546eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 547eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean /* 548eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * 16 vs 24-bit logic here 549eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean */ 550eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean switch (cached_output_hardware_config.format) { 551eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S16_LE: 552eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // the output format is the same as the input format, so just write it out 553eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 554eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 555eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S24_3LE: 556eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // 16-bit LE2 - 24-bit LE3 557eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_write_buff_bytes = 558eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean convert_16_to_24_3(write_buff, num_write_buff_bytes / 2, out->conversion_buffer); 559eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean write_buff = out->conversion_buffer; 560eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 561eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 562eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean default: 563eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // hmmmmm..... 564eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:Unknown Format!!!"); 565eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 566eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 567eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 568eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (write_buff != NULL && num_write_buff_bytes != 0) { 569eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean pcm_write(out->pcm, write_buff, num_write_buff_bytes); 570eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 57119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 57219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 57319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->dev->lock); 57419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 57519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return bytes; 57619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 57719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonerr: 57819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 579f9953b7d52bcf560b15efde807f41cf0903e875dAmit Shekhar pthread_mutex_unlock(&out->dev->lock); 58019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret != 0) { 58119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / 58219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out_get_sample_rate(&stream->common)); 58319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 58419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 58519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return bytes; 58619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 58719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 58819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_get_render_position(const struct audio_stream_out *stream, 58919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson uint32_t *dsp_frames) 59019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 59119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 59219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 59319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 59419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 59519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 59619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 59719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 59819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 59919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 60019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 60119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 60219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 60319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 60419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_get_next_write_timestamp(const struct audio_stream_out *stream, 60519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int64_t *timestamp) 60619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 60719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 60819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 60919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 61019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_open_output_stream(struct audio_hw_device *dev, 61146a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_io_handle_t handle, 61246a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_devices_t devices, 61346a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_output_flags_t flags, 61446a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood struct audio_config *config, 61519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out **stream_out) 61619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 617eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::out adev_open_output_stream() handle:0x%X, devices:0x%X, flags:0x%X", 618eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean handle, devices, flags); 619eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 62019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = (struct audio_device *)dev; 621eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 62219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out; 62319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 62419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); 62519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!out) 62619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOMEM; 62719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 628eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // setup function pointers 62919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_sample_rate = out_get_sample_rate; 63019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_sample_rate = out_set_sample_rate; 63119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_buffer_size = out_get_buffer_size; 63219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_channels = out_get_channels; 63319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_format = out_get_format; 63419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_format = out_set_format; 63519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.standby = out_standby; 63619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.dump = out_dump; 63719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_parameters = out_set_parameters; 63819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_parameters = out_get_parameters; 63919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.add_audio_effect = out_add_audio_effect; 64019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.remove_audio_effect = out_remove_audio_effect; 64119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_latency = out_get_latency; 64219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.set_volume = out_set_volume; 64319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.write = out_write; 64419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_render_position = out_get_render_position; 64519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 64619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 64719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->dev = adev; 64819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 649eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (output_hardware_config_is_cached) { 650eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->sample_rate = cached_output_hardware_config.rate; 65119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 652eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->format = alsa_to_fw_format_id(cached_output_hardware_config.format); 653eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (config->format != AUDIO_FORMAT_PCM_16_BIT) { 654eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Always report PCM16 for now. AudioPolicyManagerBase/AudioFlinger dont' understand 655eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // formats with more other format, so we won't get chosen (say with a 24bit DAC). 656eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) remove this when the above restriction is removed. 657eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->format = AUDIO_FORMAT_PCM_16_BIT; 658eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 65919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 660eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->channel_mask = 661eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean audio_channel_out_mask_from_count(cached_output_hardware_config.channels); 662eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO) { 663eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Always report STEREO for now. AudioPolicyManagerBase/AudioFlinger dont' understand 664eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // formats with more channels, so we won't get chosen (say with a 4-channel DAC). 665eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) remove this when the above restriction is removed. 666eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; 667eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 668eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } else { 669eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean cached_output_hardware_config = default_alsa_out_config; 670eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 671eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->format = out_get_format(&out->stream.common); 672eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->channel_mask = out_get_channels(&out->stream.common); 673eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean config->sample_rate = out_get_sample_rate(&out->stream.common); 674eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 675eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw config->sample_rate:%d", config->sample_rate); 676eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw config->format:0x%X", config->format); 677eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw config->channel_mask:0x%X", config->channel_mask); 678eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 679eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer = NULL; 680eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer_size = 0; 681eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 682eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->standby = true; 68346a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood 68419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *stream_out = &out->stream; 68519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 68619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 68719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonerr_open: 68819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(out); 68919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *stream_out = NULL; 690eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOSYS; 69119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 69219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 69319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic void adev_close_output_stream(struct audio_hw_device *dev, 69419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out *stream) 69519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 696eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::out adev_close_output_stream()"); 69719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 69819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 699eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) why are we doing this when stream get's freed at the end 700eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // because it closes the pcm device 70119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out_standby(&stream->common); 702eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 703eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean free(out->conversion_buffer); 704eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer = NULL; 705eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean out->conversion_buffer_size = 0; 706eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 70719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(stream); 70819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 70919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 71019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 71119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 71219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 71319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 71419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 71519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic char * adev_get_parameters(const struct audio_hw_device *dev, 71619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson const char *keys) 71719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 71819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return strdup(""); 71919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 72019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 72119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_init_check(const struct audio_hw_device *dev) 72219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 72319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 72419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 72519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 72619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 72719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 72819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 72919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 73019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 73119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume) 73219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 73319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 73419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 73519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 73619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 73719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 73819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 73919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 74019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 74119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 74219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 74319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 74419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 74519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 74619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 74719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 74819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 74919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 75019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 75119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 75246a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood const struct audio_config *config) 75319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 75419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 75519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 75619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 757eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean/* Helper functions */ 758eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic uint32_t in_get_sample_rate(const struct audio_stream *stream) 759eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 760eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)stream; 761eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return in->alsa_pcm_config.rate; 762eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 763eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 764eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) 765eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 766eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOSYS; 767eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 768eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 769eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic size_t in_get_buffer_size(const struct audio_stream *stream) 770eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 771eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)stream; 772eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean size_t buff_size = 773eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->alsa_pcm_config.period_size 774eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean * audio_stream_frame_size((struct audio_stream *)stream); 775eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return buff_size; 776eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 777eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 778eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic uint32_t in_get_channels(const struct audio_stream *stream) 779eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 780eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)stream; 781eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) this should be done with a num_channels_to_alsa_channels() 782eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return in->alsa_pcm_config.channels == 2 783eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_IN_MONO; 784eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 785eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 786eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic audio_format_t in_get_format(const struct audio_stream *stream) 787eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 788eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // just report 16-bit, pcm for now. 789eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return AUDIO_FORMAT_PCM_16_BIT; 790eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 791eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 792eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_set_format(struct audio_stream *stream, audio_format_t format) 793eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 794eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOSYS; 795eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 796eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 797eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_standby(struct audio_stream *stream) 798eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 799eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("-pcm-audio_hw::in in_standby() [Not Implemented]"); 800eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 801eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 802eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 803eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_dump(const struct audio_stream *stream, int fd) 804eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 805eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 806eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 807eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 808eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_set_parameters(struct audio_stream *stream, const char *kvpairs) 809eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 810eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("Vaudio_hw::in in_set_parameters() keys:%s", kvpairs); 811eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 812eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)stream; 813eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = in->dev; 814eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct str_parms *parms; 815eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean char value[32]; 816eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int param_val; 817eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int routing = 0; 818eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int ret_value = 0; 819eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 820eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean parms = str_parms_create_str(kvpairs); 821eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean pthread_mutex_lock(&adev->lock); 822eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 823eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Card/Device 824eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean param_val = str_parms_get_str(parms, "card", value, sizeof(value)); 825eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (param_val >= 0) { 826eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean adev->in_card = atoi(value); 827eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 828eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 829eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean param_val = str_parms_get_str(parms, "device", value, sizeof(value)); 830eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (param_val >= 0) { 831eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean adev->in_device = atoi(value); 832eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 833eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 834eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (adev->in_card >= 0 && adev->in_device >= 0) { 835eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ret_value = read_alsa_device_config(adev->in_card, adev->in_device, PCM_IN, &(in->alsa_pcm_config)); 836eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 837eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 838eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean pthread_mutex_unlock(&adev->lock); 839eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_destroy(parms); 840eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 841eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return ret_value; 842eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 843eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 844eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean//TODO(pmclean) it seems like both out_get_parameters() and in_get_parameters() 845eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean// could be written in terms of a get_device_parameters(io_type) 846eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 847eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic char * in_get_parameters(const struct audio_stream *stream, const char *keys) 848eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 849eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::in in_get_parameters() keys:%s", keys); 850eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 851eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)stream; 852eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = in->dev; 853eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 854eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct pcm_params * alsa_hw_params = pcm_params_get(adev->in_card, adev->in_device, PCM_IN); 855eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (alsa_hw_params == NULL) 856eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return strdup(""); 857eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 858eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct str_parms *query = str_parms_create_str(keys); 859eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct str_parms *result = str_parms_create(); 860eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 861eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int num_written = 0; 862eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean char buffer[256]; 863eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int buffer_size = sizeof(buffer)/sizeof(buffer[0]); 864eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean char* result_str = NULL; 865eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 866eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean unsigned min, max; 867eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 868eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // These keys are from hardware/libhardware/include/audio.h 869eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported sample rates 870eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { 871eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // pcm_hw_params doesn't have a list of supported samples rates, just a min and a max, so 872eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // if they are different, return a list containing those two values, otherwise just the one. 873eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE); 874eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE); 875eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 876eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 877eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", max); 878eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 879eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SAMPLING_RATE, buffer); 880eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES 881eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 882eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported channel counts 883eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { 884eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // Similarly for output channels count 885eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS); 886eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS); 887eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 888eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 889eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", max); 890eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 891eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_CHANNELS, buffer); 892eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_CHANNELS 893eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 894eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // supported sample formats 895eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { 896eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean): this is wrong. 897eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS); 898eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS); 899eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean num_written = snprintf(buffer, buffer_size, "%d", min); 900eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (min != max) { 901eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean snprintf(buffer + num_written, buffer_size - num_written, "|%d", max); 902eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 903eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, buffer); 904eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } // AUDIO_PARAMETER_STREAM_SUP_FORMATS 905eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 906eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean result_str = str_parms_to_str(result); 907eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 908eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // done with these... 909eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_destroy(query); 910eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean str_parms_destroy(result); 911eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 912eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return result_str; 913eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 914eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 915eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 916eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 917eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 918eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 919eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 920eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 921eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean{ 922eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 923eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 924eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 925eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic int in_set_gain(struct audio_stream_in *stream, float gain) { 926eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 927eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 928eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 929eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes) { 930eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in * in = (struct stream_in *)stream; 931eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 932eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean int err = pcm_read(in->pcm, buffer, bytes); 933eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 934eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return err == 0 ? bytes : 0; 935eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 936eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 937eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLeanstatic uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) { 938eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 939eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean} 940eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 94146a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwoodstatic int adev_open_input_stream(struct audio_hw_device *dev, 94246a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_io_handle_t handle, 94346a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_devices_t devices, 944eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_config *hal_config, 94519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_in **stream_in) 94619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 947eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::in adev_open_input_stream() rate:%d, chanMask:0x%X, fmt:%d", 948eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->sample_rate, 949eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->channel_mask, 950eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format); 951eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 952eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in)); 953eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (in == NULL) 954eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return -ENOMEM; 955eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 956eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // setup function pointers 957eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.get_sample_rate = in_get_sample_rate; 958eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.set_sample_rate = in_set_sample_rate; 959eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.get_buffer_size = in_get_buffer_size; 960eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.get_channels = in_get_channels; 961eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.get_format = in_get_format; 962eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.set_format = in_set_format; 963eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.standby = in_standby; 964eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.dump = in_dump; 965eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.set_parameters = in_set_parameters; 966eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.get_parameters = in_get_parameters; 967eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.add_audio_effect = in_add_audio_effect; 968eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.common.remove_audio_effect = in_remove_audio_effect; 969eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 970eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.set_gain = in_set_gain; 971eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.read = in_read; 972eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->stream.get_input_frames_lost = in_get_input_frames_lost; 973eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 974eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = (struct audio_device *)dev; 975eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->dev = adev; 976eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 977eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->standby = true; 978eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->requested_rate = hal_config->sample_rate; 979eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->alsa_pcm_config = default_alsa_in_config; 980eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 981eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean if (hal_config->sample_rate != 0) 982eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean in->alsa_pcm_config.rate = hal_config->sample_rate; 983eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 984eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) is this correct, or do we need to map from ALSA format? 985eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // hal_config->format is an audio_format_t 986eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // logical 987eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // hal_config->format = default_alsa_in_config.format; 988eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean //TODO(pmclean) use audio_format_from_pcm_format() (in hardware/audio_alsaops.h) 989eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean switch (default_alsa_in_config.format) { 990eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S32_LE: 991eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format = AUDIO_FORMAT_PCM_32_BIT; 992eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 993eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 994eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S8: 995eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format = AUDIO_FORMAT_PCM_8_BIT; 996eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 997eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 998eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S24_LE: 999eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format = AUDIO_FORMAT_PCM_8_24_BIT; 1000eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 1001eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 1002eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S24_3LE: 1003eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format = AUDIO_FORMAT_PCM_8_24_BIT; 1004eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 1005eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 1006eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean default: 1007eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean case PCM_FORMAT_S16_LE: 1008eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean hal_config->format = AUDIO_FORMAT_PCM_16_BIT; 1009eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean break; 1010eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean } 1011eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 1012eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean *stream_in = &in->stream; 1013eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 1014eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean return 0; 101519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 101619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 101719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic void adev_close_input_stream(struct audio_hw_device *dev, 101819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_in *stream) 101919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 102019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 102119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 102219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_dump(const audio_hw_device_t *device, int fd) 102319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 102419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 102519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 102619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 102719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_close(hw_device_t *device) 102819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 1029eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean ALOGV("usb:audio_hw::adev_close()"); 103019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 1031eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = (struct audio_device *)device; 103219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(device); 1033eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 1034eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean output_hardware_config_is_cached = false; 1035eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean 103619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 103719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 103819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 103919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_open(const hw_module_t* module, const char* name, 104019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson hw_device_t** device) 104119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 1042eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean // ALOGV("usb:audio_hw::adev_open(%s)", name); 104319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 104419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 104519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 104619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 1047eedc92ea4df9ab1429aaa38bbd590ab7ee20faa1Paul McLean struct audio_device *adev = calloc(1, sizeof(struct audio_device)); 104819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!adev) 104919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOMEM; 105019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 105119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; 105285e08e26258711f2fd672d9a920d88bf91410f6bEric Laurent adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; 105319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.module = (struct hw_module_t *) module; 105419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.close = adev_close; 105519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 105619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.init_check = adev_init_check; 105719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_voice_volume = adev_set_voice_volume; 105819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_master_volume = adev_set_master_volume; 105919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_mode = adev_set_mode; 106019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_mic_mute = adev_set_mic_mute; 106119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_mic_mute = adev_get_mic_mute; 106219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_parameters = adev_set_parameters; 106319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_parameters = adev_get_parameters; 106419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; 106519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.open_output_stream = adev_open_output_stream; 106619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.close_output_stream = adev_close_output_stream; 106719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.open_input_stream = adev_open_input_stream; 106819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.close_input_stream = adev_close_input_stream; 106919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.dump = adev_dump; 107019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 107119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *device = &adev->hw_device.common; 107219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 107319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 107419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 107519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 107619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic struct hw_module_methods_t hal_module_methods = { 107719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .open = adev_open, 107819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 107919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 108019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct audio_module HAL_MODULE_INFO_SYM = { 108119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .common = { 108219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .tag = HARDWARE_MODULE_TAG, 108346a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood .module_api_version = AUDIO_MODULE_API_VERSION_0_1, 108446a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood .hal_api_version = HARDWARE_HAL_API_VERSION, 108519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .id = AUDIO_HARDWARE_MODULE_ID, 108619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .name = "USB audio HW HAL", 108719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .author = "The Android Open Source Project", 108819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .methods = &hal_module_methods, 108919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson }, 109019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 1091