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 3619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct pcm_config pcm_config = { 3719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .channels = 2, 3819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .rate = 44100, 3919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .period_size = 1024, 4019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .period_count = 4, 4119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .format = PCM_FORMAT_S16_LE, 4219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 4319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 4419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct audio_device { 4519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_hw_device hw_device; 4619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 4719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_t lock; /* see note below on mutex acquisition order */ 4819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int card; 4919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int device; 5019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson bool standby; 5119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 5219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 5319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct stream_out { 5419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out stream; 5519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 5619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_t lock; /* see note below on mutex acquisition order */ 5719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct pcm *pcm; 5819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson bool standby; 5919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 6019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *dev; 6119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 6219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 6319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/** 6419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * NOTE: when multiple mutexes have to be acquired, always respect the 6519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson * following order: hw device > out stream 6619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson */ 6719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 6819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/* Helper functions */ 6919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 7019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/* must be called with hw device and output stream mutexes locked */ 7119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int start_output_stream(struct stream_out *out) 7219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 7319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = out->dev; 7419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int i; 7519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 7619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if ((adev->card < 0) || (adev->device < 0)) 7719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 7819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 7919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->pcm = pcm_open(adev->card, adev->device, PCM_OUT, &pcm_config); 8019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 8119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (out->pcm && !pcm_is_ready(out->pcm)) { 8219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson ALOGE("pcm_open() failed: %s", pcm_get_error(out->pcm)); 8319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pcm_close(out->pcm); 8419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOMEM; 8519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 8619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 8719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 8819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 8919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 9019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson/* API functions */ 9119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 9219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_sample_rate(const struct audio_stream *stream) 9319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 9419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return pcm_config.rate; 9519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 9619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 9719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) 9819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 9919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 10019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 10119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 10219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic size_t out_get_buffer_size(const struct audio_stream *stream) 10319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 10419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return pcm_config.period_size * 10519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson audio_stream_frame_size((struct audio_stream *)stream); 10619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 10719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 10819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_channels(const struct audio_stream *stream) 10919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 11019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return AUDIO_CHANNEL_OUT_STEREO; 11119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 11219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 11319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic audio_format_t out_get_format(const struct audio_stream *stream) 11419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 11519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return AUDIO_FORMAT_PCM_16_BIT; 11619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 11719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 11819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_format(struct audio_stream *stream, audio_format_t format) 11919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 12019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 12119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 12219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 12319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_standby(struct audio_stream *stream) 12419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 12519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 12619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 12719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->dev->lock); 12819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->lock); 12919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 13019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!out->standby) { 13119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pcm_close(out->pcm); 13219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->pcm = NULL; 13319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->standby = true; 13419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 13519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 13619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 13719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->dev->lock); 13819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 13919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 14019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 14119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 14219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_dump(const struct audio_stream *stream, int fd) 14319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 14419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 14519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 14619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 14719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs) 14819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 14919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 15019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = out->dev; 15119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct str_parms *parms; 15219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson char value[32]; 15319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int ret; 15419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int routing = 0; 15519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 15619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson parms = str_parms_create_str(kvpairs); 15719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&adev->lock); 15819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 15919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson ret = str_parms_get_str(parms, "card", value, sizeof(value)); 16019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret >= 0) 16119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->card = atoi(value); 16219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 16319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson ret = str_parms_get_str(parms, "device", value, sizeof(value)); 16419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret >= 0) 16519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->device = atoi(value); 16619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 16719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&adev->lock); 16819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson str_parms_destroy(parms); 16919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 17019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 17119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 17219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 17319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic char * out_get_parameters(const struct audio_stream *stream, const char *keys) 17419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 17519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return strdup(""); 17619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 17719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 17819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic uint32_t out_get_latency(const struct audio_stream_out *stream) 17919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 18019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return (pcm_config.period_size * pcm_config.period_count * 1000) / 18119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out_get_sample_rate(&stream->common); 18219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 18319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 18419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_set_volume(struct audio_stream_out *stream, float left, 18519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson float right) 18619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 18719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 18819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 18919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 19019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer, 19119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson size_t bytes) 19219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 19319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int ret; 19419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 19519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 19619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->dev->lock); 19719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_lock(&out->lock); 19819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (out->standby) { 19919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson ret = start_output_stream(out); 20019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret != 0) { 20119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson goto err; 20219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 20319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->standby = false; 20419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 20519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 20619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pcm_write(out->pcm, (void *)buffer, bytes); 20719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 20819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 20919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->dev->lock); 21019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 21119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return bytes; 21219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 21319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonerr: 21419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson pthread_mutex_unlock(&out->lock); 2151482406b70a254fc85d153a7066d7f90d724d195Amit Shekhar pthread_mutex_unlock(&out->dev->lock); 21619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (ret != 0) { 21719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / 21819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out_get_sample_rate(&stream->common)); 21919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson } 22019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 22119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return bytes; 22219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 22319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 22419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_get_render_position(const struct audio_stream_out *stream, 22519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson uint32_t *dsp_frames) 22619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 22719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 22819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 22919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 23019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 23119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 23219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 23319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 23419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 23519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) 23619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 23719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 23819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 23919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 24019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int out_get_next_write_timestamp(const struct audio_stream_out *stream, 24119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int64_t *timestamp) 24219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 24319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 24419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 24519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 24619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_open_output_stream(struct audio_hw_device *dev, 24746a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_io_handle_t handle, 24846a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_devices_t devices, 24946a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_output_flags_t flags, 25046a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood struct audio_config *config, 25119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out **stream_out) 25219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 25319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = (struct audio_device *)dev; 25419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out; 25519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int ret; 25619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 25719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); 25819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!out) 25919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOMEM; 26019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 26119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_sample_rate = out_get_sample_rate; 26219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_sample_rate = out_set_sample_rate; 26319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_buffer_size = out_get_buffer_size; 26419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_channels = out_get_channels; 26519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_format = out_get_format; 26619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_format = out_set_format; 26719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.standby = out_standby; 26819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.dump = out_dump; 26919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.set_parameters = out_set_parameters; 27019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.get_parameters = out_get_parameters; 27119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.add_audio_effect = out_add_audio_effect; 27219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.common.remove_audio_effect = out_remove_audio_effect; 27319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_latency = out_get_latency; 27419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.set_volume = out_set_volume; 27519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.write = out_write; 27619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_render_position = out_get_render_position; 27719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 27819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 27919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->dev = adev; 28019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 28146a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood config->format = out_get_format(&out->stream.common); 28246a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood config->channel_mask = out_get_channels(&out->stream.common); 28346a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood config->sample_rate = out_get_sample_rate(&out->stream.common); 28419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 28519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out->standby = true; 28619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 28746a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood adev->card = -1; 28846a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood adev->device = -1; 28946a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood 29019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *stream_out = &out->stream; 29119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 29219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 29319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonerr_open: 29419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(out); 29519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *stream_out = NULL; 29619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return ret; 29719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 29819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 29919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic void adev_close_output_stream(struct audio_hw_device *dev, 30019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_out *stream) 30119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 30219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct stream_out *out = (struct stream_out *)stream; 30319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 30419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson out_standby(&stream->common); 30519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(stream); 30619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 30719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 30819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 30919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 31019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 31119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 31219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 31319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic char * adev_get_parameters(const struct audio_hw_device *dev, 31419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson const char *keys) 31519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 31619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return strdup(""); 31719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 31819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 31919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_init_check(const struct audio_hw_device *dev) 32019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 32119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 32219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 32319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 32419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 32519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 32619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 32719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 32819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 32919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume) 33019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 33119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 33219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 33319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 33419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 33519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 33619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 33719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 33819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 33919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 34019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 34119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 34219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 34319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 34419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 34519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 34619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 34719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 34819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 34919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 35046a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood const struct audio_config *config) 35119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 35219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 35319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 35419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 35546a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwoodstatic int adev_open_input_stream(struct audio_hw_device *dev, 35646a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_io_handle_t handle, 35746a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood audio_devices_t devices, 35846a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood struct audio_config *config, 35919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_in **stream_in) 36019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 36119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOSYS; 36219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 36319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 36419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic void adev_close_input_stream(struct audio_hw_device *dev, 36519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_stream_in *stream) 36619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 36719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 36819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 36919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_dump(const audio_hw_device_t *device, int fd) 37019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 37119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 37219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 37319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 37419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_close(hw_device_t *device) 37519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 37619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev = (struct audio_device *)device; 37719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 37819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson free(device); 37919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 38019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 38119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 38219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic int adev_open(const hw_module_t* module, const char* name, 38319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson hw_device_t** device) 38419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson{ 38519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson struct audio_device *adev; 38619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson int ret; 38719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 38819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) 38919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -EINVAL; 39019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 39119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev = calloc(1, sizeof(struct audio_device)); 39219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson if (!adev) 39319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return -ENOMEM; 39419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 39519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; 39685e08e26258711f2fd672d9a920d88bf91410f6bEric Laurent adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; 39719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.module = (struct hw_module_t *) module; 39819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.common.close = adev_close; 39919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 40019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.init_check = adev_init_check; 40119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_voice_volume = adev_set_voice_volume; 40219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_master_volume = adev_set_master_volume; 40319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_mode = adev_set_mode; 40419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_mic_mute = adev_set_mic_mute; 40519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_mic_mute = adev_get_mic_mute; 40619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.set_parameters = adev_set_parameters; 40719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_parameters = adev_get_parameters; 40819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; 40919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.open_output_stream = adev_open_output_stream; 41019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.close_output_stream = adev_close_output_stream; 41119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.open_input_stream = adev_open_input_stream; 41219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.close_input_stream = adev_close_input_stream; 41319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson adev->hw_device.dump = adev_dump; 41419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 41519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson *device = &adev->hw_device.common; 41619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 41719957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson return 0; 41819957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson} 41919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 42019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstatic struct hw_module_methods_t hal_module_methods = { 42119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .open = adev_open, 42219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 42319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson 42419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilsonstruct audio_module HAL_MODULE_INFO_SYM = { 42519957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .common = { 42619957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .tag = HARDWARE_MODULE_TAG, 42746a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood .module_api_version = AUDIO_MODULE_API_VERSION_0_1, 42846a9809e9cd50af84f3e554c3d4ac214a8519831Mike Lockwood .hal_api_version = HARDWARE_HAL_API_VERSION, 42919957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .id = AUDIO_HARDWARE_MODULE_ID, 43019957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .name = "USB audio HW HAL", 43119957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .author = "The Android Open Source Project", 43219957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson .methods = &hal_module_methods, 43319957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson }, 43419957a37a0f92257d8cccb5cbcb6e57a836d33acSimon Wilson}; 435