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 30 void 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 65 int 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 89 void 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 */ 102 unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy) 103 { 104 return proxy->alsa_config.rate; 105 } 106 107 /* 108 * Format 109 */ 110 enum pcm_format proxy_get_format(const alsa_device_proxy * proxy) 111 { 112 return proxy->alsa_config.format; 113 } 114 115 /* 116 * Channel Count 117 */ 118 unsigned proxy_get_channel_count(const alsa_device_proxy * proxy) 119 { 120 return proxy->alsa_config.channels; 121 } 122 123 /* 124 * Other 125 */ 126 unsigned int proxy_get_period_size(const alsa_device_proxy * proxy) 127 { 128 return proxy->alsa_config.period_size; 129 } 130 131 unsigned int proxy_get_period_count(const alsa_device_proxy * proxy) 132 { 133 return proxy->alsa_config.period_count; 134 } 135 136 unsigned 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 */ 145 int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count) 146 { 147 return pcm_write(proxy->pcm, data, count); 148 } 149 150 int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count) 151 { 152 return pcm_read(proxy->pcm, data, count); 153 } 154