blob: e15f093cff39e98262a6842ee17cbafda3dca866 [file] [log] [blame]
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001/*
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_init(alsa_device_proxy * proxy)
31//{
32// proxy->profile = NULL;
33//
34// proxy->alsa_config.format = DEFAULT_SAMPLE_FORMAT;
35// proxy->alsa_config.rate = DEFAULT_SAMPLE_RATE;
36// proxy->alsa_config.channels = DEFAULT_CHANNEL_COUNT;
37//
38// proxy->alsa_config.period_size = DEFAULT_PERIOD_SIZE;
39// proxy->alsa_config.period_count = DEFAULT_PERIOD_COUNT;
40//
41// proxy->pcm = NULL;
42//}
43
44void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
45 struct pcm_config * config)
46{
47 ALOGV("proxy_prepare()");
48
49 proxy->profile = profile;
50
Paul McLeanaf5187e2014-08-12 13:57:10 -070051#ifdef LOG_PCM_PARAMS
Paul McLeanc88e6ae2014-07-16 09:48:34 -070052 log_pcm_config(config, "proxy_setup()");
53#endif
54
55 proxy->alsa_config.format =
56 config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)
57 ? config->format : profile->default_config.format;
58 proxy->alsa_config.rate =
59 config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)
60 ? config->rate : profile->default_config.rate;
61 proxy->alsa_config.channels =
62 config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)
63 ? config->channels : profile->default_config.channels;
64
65 proxy->alsa_config.period_count = profile->default_config.period_count;
66 proxy->alsa_config.period_size =
67 profile_get_period_size(proxy->profile, proxy->alsa_config.rate);
68
Mike Lockwood7de76b22014-08-14 09:34:54 -070069 // Hack for USB accessory audio.
70 // Here we set the correct value for period_count if tinyalsa fails to get it from the
71 // f_audio_source driver.
72 if (proxy->alsa_config.period_count == 0) {
73 proxy->alsa_config.period_count = 4;
74 }
75
Paul McLeanc88e6ae2014-07-16 09:48:34 -070076 proxy->pcm = NULL;
77}
78
79int proxy_open(alsa_device_proxy * proxy)
80{
81 alsa_device_profile* profile = proxy->profile;
82
83 ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device,
84 profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN");
85
86 proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config);
87 if (proxy->pcm == NULL) {
88 return -ENOMEM;
89 }
90
91 if (!pcm_is_ready(proxy->pcm)) {
92 ALOGE("[%s] proxy_open() pcm_open() failed: %s", LOG_TAG, pcm_get_error(proxy->pcm));
93#ifdef LOG_PCM_PARAMS
94 log_pcm_config(&proxy->alsa_config, "config");
95#endif
96 pcm_close(proxy->pcm);
97 proxy->pcm = NULL;
98 return -ENOMEM;
99 }
100
101 return 0;
102}
103
104void proxy_close(alsa_device_proxy * proxy)
105{
106 pcm_close(proxy->pcm);
107 proxy->pcm = NULL;
108}
109
110/*
111 * Sample Rate
112 */
113unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy)
114{
115 return proxy->alsa_config.rate;
116}
117
118/*
119 * Format
120 */
121enum pcm_format proxy_get_format(const alsa_device_proxy * proxy)
122{
123 return proxy->alsa_config.format;
124}
125
126/*
127 * Channel Count
128 */
129unsigned proxy_get_channel_count(const alsa_device_proxy * proxy)
130{
131 return proxy->alsa_config.channels;
132}
133
134/*
135 * Other
136 */
137unsigned int proxy_get_period_size(const alsa_device_proxy * proxy)
138{
139 return proxy->alsa_config.period_size;
140}
141
142unsigned int proxy_get_period_count(const alsa_device_proxy * proxy)
143{
144 return proxy->alsa_config.period_count;
145}
146
147unsigned proxy_get_latency(const alsa_device_proxy * proxy)
148{
149 return (proxy_get_period_size(proxy) * proxy_get_period_count(proxy) * 1000)
150 / proxy_get_sample_rate(proxy);
151}
152
153/*
154 * I/O
155 */
156int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count)
157{
158 return pcm_write(proxy->pcm, data, count);
159}
160
161int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count)
162{
163 return pcm_read(proxy->pcm, data, count);
164}