1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "alsa_device_proxy" 18/*#define LOG_NDEBUG 0*/ 19/*#define LOG_PCM_PARAMS 0*/ 20 21#include <log/log.h> 22 23#include "alsa_device_proxy.h" 24 25#include "logging.h" 26 27#define DEFAULT_PERIOD_SIZE 1024 28#define DEFAULT_PERIOD_COUNT 2 29 30void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile, 31 struct pcm_config * config) 32{ 33 ALOGV("proxy_prepare()"); 34 35 proxy->profile = profile; 36 37#ifdef LOG_PCM_PARAMS 38 log_pcm_config(config, "proxy_setup()"); 39#endif 40 41 proxy->alsa_config.format = 42 config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format) 43 ? config->format : profile->default_config.format; 44 proxy->alsa_config.rate = 45 config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate) 46 ? config->rate : profile->default_config.rate; 47 proxy->alsa_config.channels = 48 config->channels != 0 && profile_is_channel_count_valid(profile, config->channels) 49 ? config->channels : profile->default_config.channels; 50 51 proxy->alsa_config.period_count = profile->default_config.period_count; 52 proxy->alsa_config.period_size = 53 profile_get_period_size(proxy->profile, proxy->alsa_config.rate); 54 55 // Hack for USB accessory audio. 56 // Here we set the correct value for period_count if tinyalsa fails to get it from the 57 // f_audio_source driver. 58 if (proxy->alsa_config.period_count == 0) { 59 proxy->alsa_config.period_count = 4; 60 } 61 62 proxy->pcm = NULL; 63} 64 65int proxy_open(alsa_device_proxy * proxy) 66{ 67 alsa_device_profile* profile = proxy->profile; 68 ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device, 69 profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN"); 70 71 proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config); 72 if (proxy->pcm == NULL) { 73 return -ENOMEM; 74 } 75 76 if (!pcm_is_ready(proxy->pcm)) { 77 ALOGE("[%s] proxy_open() pcm_open() failed: %s", LOG_TAG, pcm_get_error(proxy->pcm)); 78#ifdef LOG_PCM_PARAMS 79 log_pcm_config(&proxy->alsa_config, "config"); 80#endif 81 pcm_close(proxy->pcm); 82 proxy->pcm = NULL; 83 return -ENOMEM; 84 } 85 86 return 0; 87} 88 89void proxy_close(alsa_device_proxy * proxy) 90{ 91 ALOGV("proxy_close() [pcm:%p]", proxy->pcm); 92 93 if (proxy->pcm != NULL) { 94 pcm_close(proxy->pcm); 95 proxy->pcm = NULL; 96 } 97} 98 99/* 100 * Sample Rate 101 */ 102unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy) 103{ 104 return proxy->alsa_config.rate; 105} 106 107/* 108 * Format 109 */ 110enum pcm_format proxy_get_format(const alsa_device_proxy * proxy) 111{ 112 return proxy->alsa_config.format; 113} 114 115/* 116 * Channel Count 117 */ 118unsigned proxy_get_channel_count(const alsa_device_proxy * proxy) 119{ 120 return proxy->alsa_config.channels; 121} 122 123/* 124 * Other 125 */ 126unsigned int proxy_get_period_size(const alsa_device_proxy * proxy) 127{ 128 return proxy->alsa_config.period_size; 129} 130 131unsigned int proxy_get_period_count(const alsa_device_proxy * proxy) 132{ 133 return proxy->alsa_config.period_count; 134} 135 136unsigned proxy_get_latency(const alsa_device_proxy * proxy) 137{ 138 return (proxy_get_period_size(proxy) * proxy_get_period_count(proxy) * 1000) 139 / proxy_get_sample_rate(proxy); 140} 141 142/* 143 * I/O 144 */ 145int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count) 146{ 147 return pcm_write(proxy->pcm, data, count); 148} 149 150int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count) 151{ 152 return pcm_read(proxy->pcm, data, count); 153} 154