blob: d899d6b958c758083822ac750d1e8f9abf546745 [file] [log] [blame]
Simon Wilson19957a32012-04-06 16:17:12 -07001/*
2 * Copyright (C) 2012 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
Paul McLean9ab869a2015-01-13 09:37:06 -080017#define LOG_TAG "modules.usbaudio.audio_hal"
Paul McLeancf611912014-04-28 13:03:18 -070018/*#define LOG_NDEBUG 0*/
Simon Wilson19957a32012-04-06 16:17:12 -070019
20#include <errno.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070021#include <inttypes.h>
Simon Wilson19957a32012-04-06 16:17:12 -070022#include <pthread.h>
23#include <stdint.h>
Simon Wilson19957a32012-04-06 16:17:12 -070024#include <stdlib.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070025#include <sys/time.h>
Simon Wilson19957a32012-04-06 16:17:12 -070026
Mark Salyzyn88e458a2014-04-28 12:30:44 -070027#include <log/log.h>
Simon Wilson19957a32012-04-06 16:17:12 -070028#include <cutils/str_parms.h>
29#include <cutils/properties.h>
30
Simon Wilson19957a32012-04-06 16:17:12 -070031#include <hardware/audio.h>
Paul McLeane32cbc12014-06-25 10:42:07 -070032#include <hardware/audio_alsaops.h>
33#include <hardware/hardware.h>
34
35#include <system/audio.h>
Simon Wilson19957a32012-04-06 16:17:12 -070036
37#include <tinyalsa/asoundlib.h>
38
Paul McLeanc2201152014-07-16 13:46:07 -070039#include <audio_utils/channels.h>
40
Andy Hung03576be2014-07-21 21:16:45 -070041/* FOR TESTING:
42 * Set k_force_channels to force the number of channels to present to AudioFlinger.
43 * 0 disables (this is default: present the device channels to AudioFlinger).
44 * 2 forces to legacy stereo mode.
45 *
46 * Others values can be tried (up to 8).
47 * TODO: AudioFlinger cannot support more than 8 active output channels
48 * at this time, so limiting logic needs to be put here or communicated from above.
49 */
50static const unsigned k_force_channels = 0;
51
Paul McLeanc88e6ae2014-07-16 09:48:34 -070052#include "alsa_device_profile.h"
53#include "alsa_device_proxy.h"
Paul McLean9ab869a2015-01-13 09:37:06 -080054#include "alsa_logging.h"
Paul McLeanf62d75e2014-07-11 15:14:19 -070055
Paul McLeanc88e6ae2014-07-16 09:48:34 -070056#define DEFAULT_INPUT_BUFFER_SIZE_MS 20
Paul McLeanf62d75e2014-07-11 15:14:19 -070057
Simon Wilson19957a32012-04-06 16:17:12 -070058struct audio_device {
59 struct audio_hw_device hw_device;
60
61 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Paul McLeaneedc92e2013-12-19 15:46:15 -080062
63 /* output */
Paul McLeanc88e6ae2014-07-16 09:48:34 -070064 alsa_device_profile out_profile;
Paul McLeaneedc92e2013-12-19 15:46:15 -080065
66 /* input */
Paul McLeanc88e6ae2014-07-16 09:48:34 -070067 alsa_device_profile in_profile;
Paul McLeaneedc92e2013-12-19 15:46:15 -080068
Eric Laurent253def92014-09-14 12:18:18 -070069 bool mic_muted;
70
Simon Wilson19957a32012-04-06 16:17:12 -070071 bool standby;
72};
73
74struct stream_out {
75 struct audio_stream_out stream;
76
Paul McLeaneedc92e2013-12-19 15:46:15 -080077 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Eric Laurent70318092015-06-19 17:49:17 -070078 pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
Paul McLeaneedc92e2013-12-19 15:46:15 -080079 bool standby;
80
Paul McLeanc88e6ae2014-07-16 09:48:34 -070081 struct audio_device *dev; /* hardware information - only using this for the lock */
82
Paul McLean65ec72b2015-02-18 09:13:24 -080083 alsa_device_profile * profile; /* Points to the alsa_device_profile in the audio_device */
Paul McLeanc88e6ae2014-07-16 09:48:34 -070084 alsa_device_proxy proxy; /* state of the stream */
Paul McLeaneedc92e2013-12-19 15:46:15 -080085
Andy Hung03576be2014-07-21 21:16:45 -070086 unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
87 * This may differ from the device channel count when
88 * the device is not compatible with AudioFlinger
89 * capabilities, e.g. exposes too many channels or
90 * too few channels. */
Andy Hung182ddc72015-05-05 23:37:30 -070091 audio_channel_mask_t hal_channel_mask; /* channel mask exposed to AudioFlinger. */
92
Paul McLeaneedc92e2013-12-19 15:46:15 -080093 void * conversion_buffer; /* any conversions are put into here
94 * they could come from here too if
95 * there was a previous conversion */
96 size_t conversion_buffer_size; /* in bytes */
97};
98
Paul McLeaneedc92e2013-12-19 15:46:15 -080099struct stream_in {
100 struct audio_stream_in stream;
101
Eric Laurent70318092015-06-19 17:49:17 -0700102 pthread_mutex_t lock; /* see note below on mutex acquisition order */
103 pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by capture thread */
Simon Wilson19957a32012-04-06 16:17:12 -0700104 bool standby;
105
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700106 struct audio_device *dev; /* hardware information - only using this for the lock */
Paul McLeaneedc92e2013-12-19 15:46:15 -0800107
Paul McLean65ec72b2015-02-18 09:13:24 -0800108 alsa_device_profile * profile; /* Points to the alsa_device_profile in the audio_device */
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700109 alsa_device_proxy proxy; /* state of the stream */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700110
Paul McLean2cfd81b2014-09-15 12:32:23 -0700111 unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
112 * This may differ from the device channel count when
113 * the device is not compatible with AudioFlinger
114 * capabilities, e.g. exposes too many channels or
115 * too few channels. */
Andy Hung780f1f82015-04-22 22:14:39 -0700116 audio_channel_mask_t hal_channel_mask; /* channel mask exposed to AudioFlinger. */
117
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700118 /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */
Paul McLean30f41852014-04-16 15:44:20 -0700119 void * conversion_buffer; /* any conversions are put into here
120 * they could come from here too if
121 * there was a previous conversion */
122 size_t conversion_buffer_size; /* in bytes */
Simon Wilson19957a32012-04-06 16:17:12 -0700123};
124
Paul McLeaneedc92e2013-12-19 15:46:15 -0800125/*
Eric Laurent70318092015-06-19 17:49:17 -0700126 * NOTE: when multiple mutexes have to be acquired, always take the
127 * stream_in or stream_out mutex first, followed by the audio_device mutex.
128 * stream pre_lock is always acquired before stream lock to prevent starvation of control thread by
129 * higher priority playback or capture thread.
130 */
131
132/*
Paul McLean0f1753e2014-12-02 12:36:45 -0700133 * Extract the card and device numbers from the supplied key/value pairs.
134 * kvpairs A null-terminated string containing the key/value pairs or card and device.
135 * i.e. "card=1;device=42"
136 * card A pointer to a variable to receive the parsed-out card number.
137 * device A pointer to a variable to receive the parsed-out device number.
138 * NOTE: The variables pointed to by card and device return -1 (undefined) if the
139 * associated key/value pair is not found in the provided string.
Paul McLean65ec72b2015-02-18 09:13:24 -0800140 * Return true if the kvpairs string contain a card/device spec, false otherwise.
Paul McLean0f1753e2014-12-02 12:36:45 -0700141 */
Paul McLean65ec72b2015-02-18 09:13:24 -0800142static bool parse_card_device_params(const char *kvpairs, int *card, int *device)
Paul McLean0f1753e2014-12-02 12:36:45 -0700143{
144 struct str_parms * parms = str_parms_create_str(kvpairs);
145 char value[32];
146 int param_val;
147
148 // initialize to "undefined" state.
149 *card = -1;
150 *device = -1;
151
152 param_val = str_parms_get_str(parms, "card", value, sizeof(value));
153 if (param_val >= 0) {
154 *card = atoi(value);
155 }
156
157 param_val = str_parms_get_str(parms, "device", value, sizeof(value));
158 if (param_val >= 0) {
159 *device = atoi(value);
160 }
161
162 str_parms_destroy(parms);
Paul McLean65ec72b2015-02-18 09:13:24 -0800163
164 return *card >= 0 && *device >= 0;
Paul McLean0f1753e2014-12-02 12:36:45 -0700165}
166
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700167static char * device_get_parameters(alsa_device_profile * profile, const char * keys)
Paul McLeaneedc92e2013-12-19 15:46:15 -0800168{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700169 if (profile->card < 0 || profile->device < 0) {
170 return strdup("");
Paul McLeaneedc92e2013-12-19 15:46:15 -0800171 }
Paul McLeane32cbc12014-06-25 10:42:07 -0700172
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700173 struct str_parms *query = str_parms_create_str(keys);
174 struct str_parms *result = str_parms_create();
Paul McLeane32cbc12014-06-25 10:42:07 -0700175
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700176 /* These keys are from hardware/libhardware/include/audio.h */
177 /* supported sample rates */
178 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
179 char* rates_list = profile_get_sample_rate_strs(profile);
180 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
181 rates_list);
182 free(rates_list);
Paul McLeane32cbc12014-06-25 10:42:07 -0700183 }
184
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700185 /* supported channel counts */
186 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
187 char* channels_list = profile_get_channel_count_strs(profile);
188 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
189 channels_list);
190 free(channels_list);
Paul McLeane32cbc12014-06-25 10:42:07 -0700191 }
192
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700193 /* supported sample formats */
194 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
195 char * format_params = profile_get_format_strs(profile);
196 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS,
197 format_params);
198 free(format_params);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700199 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700200 str_parms_destroy(query);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700201
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700202 char* result_str = str_parms_to_str(result);
203 str_parms_destroy(result);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700204
Paul McLean65ec72b2015-02-18 09:13:24 -0800205 ALOGV("device_get_parameters = %s", result_str);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700206
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700207 return result_str;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800208}
209
Eric Laurent70318092015-06-19 17:49:17 -0700210void lock_input_stream(struct stream_in *in)
211{
212 pthread_mutex_lock(&in->pre_lock);
213 pthread_mutex_lock(&in->lock);
214 pthread_mutex_unlock(&in->pre_lock);
215}
216
217void lock_output_stream(struct stream_out *out)
218{
219 pthread_mutex_lock(&out->pre_lock);
220 pthread_mutex_lock(&out->lock);
221 pthread_mutex_unlock(&out->pre_lock);
222}
223
Paul McLeaneedc92e2013-12-19 15:46:15 -0800224/*
225 * HAl Functions
226 */
Simon Wilson19957a32012-04-06 16:17:12 -0700227/**
228 * NOTE: when multiple mutexes have to be acquired, always respect the
229 * following order: hw device > out stream
230 */
231
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700232/*
233 * OUT functions
234 */
Simon Wilson19957a32012-04-06 16:17:12 -0700235static uint32_t out_get_sample_rate(const struct audio_stream *stream)
236{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700237 uint32_t rate = proxy_get_sample_rate(&((struct stream_out*)stream)->proxy);
238 ALOGV("out_get_sample_rate() = %d", rate);
239 return rate;
Simon Wilson19957a32012-04-06 16:17:12 -0700240}
241
242static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
243{
244 return 0;
245}
246
247static size_t out_get_buffer_size(const struct audio_stream *stream)
248{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700249 const struct stream_out* out = (const struct stream_out*)stream;
250 size_t buffer_size =
251 proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700252 return buffer_size;
Simon Wilson19957a32012-04-06 16:17:12 -0700253}
254
255static uint32_t out_get_channels(const struct audio_stream *stream)
256{
Andy Hung03576be2014-07-21 21:16:45 -0700257 const struct stream_out *out = (const struct stream_out*)stream;
Andy Hung182ddc72015-05-05 23:37:30 -0700258 return out->hal_channel_mask;
Simon Wilson19957a32012-04-06 16:17:12 -0700259}
260
261static audio_format_t out_get_format(const struct audio_stream *stream)
262{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700263 /* Note: The HAL doesn't do any FORMAT conversion at this time. It
264 * Relies on the framework to provide data in the specified format.
265 * This could change in the future.
266 */
267 alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
268 audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700269 return format;
Simon Wilson19957a32012-04-06 16:17:12 -0700270}
271
272static int out_set_format(struct audio_stream *stream, audio_format_t format)
273{
274 return 0;
275}
276
277static int out_standby(struct audio_stream *stream)
278{
279 struct stream_out *out = (struct stream_out *)stream;
280
Eric Laurent70318092015-06-19 17:49:17 -0700281 lock_output_stream(out);
Simon Wilson19957a32012-04-06 16:17:12 -0700282 if (!out->standby) {
Eric Laurent70318092015-06-19 17:49:17 -0700283 pthread_mutex_lock(&out->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700284 proxy_close(&out->proxy);
Eric Laurent70318092015-06-19 17:49:17 -0700285 pthread_mutex_unlock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700286 out->standby = true;
287 }
Simon Wilson19957a32012-04-06 16:17:12 -0700288 pthread_mutex_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700289
290 return 0;
291}
292
293static int out_dump(const struct audio_stream *stream, int fd)
294{
295 return 0;
296}
297
298static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
299{
Paul McLean65ec72b2015-02-18 09:13:24 -0800300 ALOGV("out_set_parameters() keys:%s", kvpairs);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800301
Simon Wilson19957a32012-04-06 16:17:12 -0700302 struct stream_out *out = (struct stream_out *)stream;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700303
Simon Wilson19957a32012-04-06 16:17:12 -0700304 int routing = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800305 int ret_value = 0;
Eric Laurent05333d42014-08-04 20:29:17 -0700306 int card = -1;
307 int device = -1;
Simon Wilson19957a32012-04-06 16:17:12 -0700308
Paul McLean65ec72b2015-02-18 09:13:24 -0800309 if (!parse_card_device_params(kvpairs, &card, &device)) {
310 // nothing to do
311 return ret_value;
312 }
313
Eric Laurent70318092015-06-19 17:49:17 -0700314 lock_output_stream(out);
Paul McLean65ec72b2015-02-18 09:13:24 -0800315 /* Lock the device because that is where the profile lives */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700316 pthread_mutex_lock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700317
Paul McLean65ec72b2015-02-18 09:13:24 -0800318 if (!profile_is_cached_for(out->profile, card, device)) {
Eric Laurent05333d42014-08-04 20:29:17 -0700319 /* cannot read pcm device info if playback is active */
320 if (!out->standby)
321 ret_value = -ENOSYS;
322 else {
323 int saved_card = out->profile->card;
324 int saved_device = out->profile->device;
325 out->profile->card = card;
326 out->profile->device = device;
327 ret_value = profile_read_device_info(out->profile) ? 0 : -EINVAL;
328 if (ret_value != 0) {
329 out->profile->card = saved_card;
330 out->profile->device = saved_device;
331 }
332 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800333 }
Paul McLean2c6196f2014-08-20 16:50:25 -0700334
Paul McLeanf62d75e2014-07-11 15:14:19 -0700335 pthread_mutex_unlock(&out->dev->lock);
Eric Laurent70318092015-06-19 17:49:17 -0700336 pthread_mutex_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700337
Paul McLeaneedc92e2013-12-19 15:46:15 -0800338 return ret_value;
Simon Wilson19957a32012-04-06 16:17:12 -0700339}
340
Paul McLeanf62d75e2014-07-11 15:14:19 -0700341static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
342{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700343 struct stream_out *out = (struct stream_out *)stream;
Eric Laurent70318092015-06-19 17:49:17 -0700344 lock_output_stream(out);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700345 pthread_mutex_lock(&out->dev->lock);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700346
347 char * params_str = device_get_parameters(out->profile, keys);
348
349 pthread_mutex_unlock(&out->lock);
350 pthread_mutex_unlock(&out->dev->lock);
351
352 return params_str;
353}
354
Simon Wilson19957a32012-04-06 16:17:12 -0700355static uint32_t out_get_latency(const struct audio_stream_out *stream)
356{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700357 alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
358 return proxy_get_latency(proxy);
Simon Wilson19957a32012-04-06 16:17:12 -0700359}
360
Paul McLean30f41852014-04-16 15:44:20 -0700361static int out_set_volume(struct audio_stream_out *stream, float left, float right)
Simon Wilson19957a32012-04-06 16:17:12 -0700362{
363 return -ENOSYS;
364}
365
Paul McLeaneedc92e2013-12-19 15:46:15 -0800366/* must be called with hw device and output stream mutexes locked */
367static int start_output_stream(struct stream_out *out)
368{
Paul McLean65ec72b2015-02-18 09:13:24 -0800369 ALOGV("start_output_stream(card:%d device:%d)", out->profile->card, out->profile->device);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800370
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700371 return proxy_open(&out->proxy);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800372}
373
374static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes)
Simon Wilson19957a32012-04-06 16:17:12 -0700375{
376 int ret;
377 struct stream_out *out = (struct stream_out *)stream;
378
Eric Laurent70318092015-06-19 17:49:17 -0700379 lock_output_stream(out);
Simon Wilson19957a32012-04-06 16:17:12 -0700380 if (out->standby) {
Eric Laurent70318092015-06-19 17:49:17 -0700381 pthread_mutex_lock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700382 ret = start_output_stream(out);
Eric Laurent70318092015-06-19 17:49:17 -0700383 pthread_mutex_unlock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700384 if (ret != 0) {
385 goto err;
386 }
387 out->standby = false;
388 }
Eric Laurent05333d42014-08-04 20:29:17 -0700389
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700390 alsa_device_proxy* proxy = &out->proxy;
Mark Salyzyn88e458a2014-04-28 12:30:44 -0700391 const void * write_buff = buffer;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800392 int num_write_buff_bytes = bytes;
Andy Hung03576be2014-07-21 21:16:45 -0700393 const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */
394 const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */
Paul McLean30f41852014-04-16 15:44:20 -0700395 if (num_device_channels != num_req_channels) {
Andy Hung03576be2014-07-21 21:16:45 -0700396 /* allocate buffer */
397 const size_t required_conversion_buffer_size =
398 bytes * num_device_channels / num_req_channels;
399 if (required_conversion_buffer_size > out->conversion_buffer_size) {
400 out->conversion_buffer_size = required_conversion_buffer_size;
401 out->conversion_buffer = realloc(out->conversion_buffer,
402 out->conversion_buffer_size);
403 }
404 /* convert data */
405 const audio_format_t audio_format = out_get_format(&(out->stream.common));
406 const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800407 num_write_buff_bytes =
Andy Hung03576be2014-07-21 21:16:45 -0700408 adjust_channels(write_buff, num_req_channels,
409 out->conversion_buffer, num_device_channels,
410 sample_size_in_bytes, num_write_buff_bytes);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800411 write_buff = out->conversion_buffer;
412 }
413
Paul McLeaneedc92e2013-12-19 15:46:15 -0800414 if (write_buff != NULL && num_write_buff_bytes != 0) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700415 proxy_write(&out->proxy, write_buff, num_write_buff_bytes);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800416 }
Simon Wilson19957a32012-04-06 16:17:12 -0700417
418 pthread_mutex_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700419
420 return bytes;
421
422err:
423 pthread_mutex_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700424 if (ret != 0) {
Eric Laurentc5ae6a02014-07-02 13:45:32 -0700425 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Simon Wilson19957a32012-04-06 16:17:12 -0700426 out_get_sample_rate(&stream->common));
427 }
428
429 return bytes;
430}
431
Paul McLean30f41852014-04-16 15:44:20 -0700432static int out_get_render_position(const struct audio_stream_out *stream, uint32_t *dsp_frames)
Simon Wilson19957a32012-04-06 16:17:12 -0700433{
434 return -EINVAL;
435}
436
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700437static int out_get_presentation_position(const struct audio_stream_out *stream,
438 uint64_t *frames, struct timespec *timestamp)
439{
Andy Hungc9515ce2015-08-04 15:05:19 -0700440 struct stream_out *out = (struct stream_out *)stream; // discard const qualifier
441 lock_output_stream(out);
442
443 const alsa_device_proxy *proxy = &out->proxy;
444 const int ret = proxy_get_presentation_position(proxy, frames, timestamp);
445
446 pthread_mutex_unlock(&out->lock);
Andy Hungc9515ce2015-08-04 15:05:19 -0700447 return ret;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700448}
449
Simon Wilson19957a32012-04-06 16:17:12 -0700450static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
451{
452 return 0;
453}
454
455static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
456{
457 return 0;
458}
459
Paul McLean30f41852014-04-16 15:44:20 -0700460static int out_get_next_write_timestamp(const struct audio_stream_out *stream, int64_t *timestamp)
Simon Wilson19957a32012-04-06 16:17:12 -0700461{
462 return -EINVAL;
463}
464
465static int adev_open_output_stream(struct audio_hw_device *dev,
Mike Lockwood46a98092012-04-24 16:41:18 -0700466 audio_io_handle_t handle,
467 audio_devices_t devices,
468 audio_output_flags_t flags,
469 struct audio_config *config,
Eric Laurentf5e24692014-07-27 16:14:57 -0700470 struct audio_stream_out **stream_out,
Paul McLean0f1753e2014-12-02 12:36:45 -0700471 const char *address /*__unused*/)
Simon Wilson19957a32012-04-06 16:17:12 -0700472{
Paul McLean65ec72b2015-02-18 09:13:24 -0800473 ALOGV("adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X, addr:%s",
Paul McLean0f1753e2014-12-02 12:36:45 -0700474 handle, devices, flags, address);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800475
Simon Wilson19957a32012-04-06 16:17:12 -0700476 struct audio_device *adev = (struct audio_device *)dev;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800477
Simon Wilson19957a32012-04-06 16:17:12 -0700478 struct stream_out *out;
Simon Wilson19957a32012-04-06 16:17:12 -0700479
480 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
481 if (!out)
482 return -ENOMEM;
483
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700484 /* setup function pointers */
Simon Wilson19957a32012-04-06 16:17:12 -0700485 out->stream.common.get_sample_rate = out_get_sample_rate;
486 out->stream.common.set_sample_rate = out_set_sample_rate;
487 out->stream.common.get_buffer_size = out_get_buffer_size;
488 out->stream.common.get_channels = out_get_channels;
489 out->stream.common.get_format = out_get_format;
490 out->stream.common.set_format = out_set_format;
491 out->stream.common.standby = out_standby;
492 out->stream.common.dump = out_dump;
493 out->stream.common.set_parameters = out_set_parameters;
494 out->stream.common.get_parameters = out_get_parameters;
495 out->stream.common.add_audio_effect = out_add_audio_effect;
496 out->stream.common.remove_audio_effect = out_remove_audio_effect;
497 out->stream.get_latency = out_get_latency;
498 out->stream.set_volume = out_set_volume;
499 out->stream.write = out_write;
500 out->stream.get_render_position = out_get_render_position;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700501 out->stream.get_presentation_position = out_get_presentation_position;
Simon Wilson19957a32012-04-06 16:17:12 -0700502 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
503
Eric Laurent70318092015-06-19 17:49:17 -0700504 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
505 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
506
Simon Wilson19957a32012-04-06 16:17:12 -0700507 out->dev = adev;
Paul McLean0f1753e2014-12-02 12:36:45 -0700508 pthread_mutex_lock(&adev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700509 out->profile = &adev->out_profile;
Paul McLeanf62d75e2014-07-11 15:14:19 -0700510
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700511 // build this to hand to the alsa_device_proxy
512 struct pcm_config proxy_config;
Paul McLean2c6196f2014-08-20 16:50:25 -0700513 memset(&proxy_config, 0, sizeof(proxy_config));
Paul McLeaneedc92e2013-12-19 15:46:15 -0800514
Paul McLean0f1753e2014-12-02 12:36:45 -0700515 /* Pull out the card/device pair */
516 parse_card_device_params(address, &(out->profile->card), &(out->profile->device));
517
518 profile_read_device_info(out->profile);
519
520 pthread_mutex_unlock(&adev->lock);
521
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700522 int ret = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800523
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700524 /* Rate */
525 if (config->sample_rate == 0) {
526 proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
527 } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) {
528 proxy_config.rate = config->sample_rate;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800529 } else {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700530 proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
531 ret = -EINVAL;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800532 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800533
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700534 /* Format */
535 if (config->format == AUDIO_FORMAT_DEFAULT) {
536 proxy_config.format = profile_get_default_format(out->profile);
537 config->format = audio_format_from_pcm_format(proxy_config.format);
538 } else {
539 enum pcm_format fmt = pcm_format_from_audio_format(config->format);
540 if (profile_is_format_valid(out->profile, fmt)) {
541 proxy_config.format = fmt;
542 } else {
543 proxy_config.format = profile_get_default_format(out->profile);
544 config->format = audio_format_from_pcm_format(proxy_config.format);
545 ret = -EINVAL;
546 }
547 }
548
549 /* Channels */
Andy Hung182ddc72015-05-05 23:37:30 -0700550 unsigned proposed_channel_count = 0;
Andy Hung03576be2014-07-21 21:16:45 -0700551 if (k_force_channels) {
552 proposed_channel_count = k_force_channels;
Andy Hung182ddc72015-05-05 23:37:30 -0700553 } else if (config->channel_mask == AUDIO_CHANNEL_NONE) {
554 proposed_channel_count = profile_get_default_channel_count(out->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700555 }
Paul McLean698dbd72015-11-03 12:24:30 -0800556
Andy Hung182ddc72015-05-05 23:37:30 -0700557 if (proposed_channel_count != 0) {
Andy Hung5e58a302015-06-10 15:17:00 -0700558 if (proposed_channel_count <= FCC_2) {
559 // use channel position mask for mono and stereo
560 config->channel_mask = audio_channel_out_mask_from_count(proposed_channel_count);
561 } else {
562 // use channel index mask for multichannel
Andy Hung182ddc72015-05-05 23:37:30 -0700563 config->channel_mask =
564 audio_channel_mask_for_index_assignment_from_count(proposed_channel_count);
Andy Hung5e58a302015-06-10 15:17:00 -0700565 }
Andy Hung182ddc72015-05-05 23:37:30 -0700566 } else {
Paul McLean698dbd72015-11-03 12:24:30 -0800567 proposed_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
Andy Hung182ddc72015-05-05 23:37:30 -0700568 }
Paul McLean698dbd72015-11-03 12:24:30 -0800569 out->hal_channel_count = proposed_channel_count;
570
Andy Hung182ddc72015-05-05 23:37:30 -0700571 /* we can expose any channel mask, and emulate internally based on channel count. */
572 out->hal_channel_mask = config->channel_mask;
573
Andy Hung03576be2014-07-21 21:16:45 -0700574 /* no validity checks are needed as proxy_prepare() forces channel_count to be valid.
575 * and we emulate any channel count discrepancies in out_write(). */
Paul McLean698dbd72015-11-03 12:24:30 -0800576 proxy_config.channels = out->hal_channel_count;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700577 proxy_prepare(&out->proxy, out->profile, &proxy_config);
578
579 /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
580 ret = 0;
581
Paul McLeaneedc92e2013-12-19 15:46:15 -0800582 out->conversion_buffer = NULL;
583 out->conversion_buffer_size = 0;
Simon Wilson19957a32012-04-06 16:17:12 -0700584
585 out->standby = true;
586
587 *stream_out = &out->stream;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700588
589 return ret;
Simon Wilson19957a32012-04-06 16:17:12 -0700590
591err_open:
592 free(out);
593 *stream_out = NULL;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800594 return -ENOSYS;
Simon Wilson19957a32012-04-06 16:17:12 -0700595}
596
597static void adev_close_output_stream(struct audio_hw_device *dev,
598 struct audio_stream_out *stream)
599{
600 struct stream_out *out = (struct stream_out *)stream;
Paul McLean65ec72b2015-02-18 09:13:24 -0800601 ALOGV("adev_close_output_stream(c:%d d:%d)", out->profile->card, out->profile->device);
Simon Wilson19957a32012-04-06 16:17:12 -0700602
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700603 /* Close the pcm device */
Simon Wilson19957a32012-04-06 16:17:12 -0700604 out_standby(&stream->common);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800605
606 free(out->conversion_buffer);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700607
Paul McLeaneedc92e2013-12-19 15:46:15 -0800608 out->conversion_buffer = NULL;
609 out->conversion_buffer_size = 0;
610
Simon Wilson19957a32012-04-06 16:17:12 -0700611 free(stream);
612}
613
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700614static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
615 const struct audio_config *config)
616{
617 /* TODO This needs to be calculated based on format/channels/rate */
618 return 320;
619}
620
621/*
622 * IN functions
623 */
624static uint32_t in_get_sample_rate(const struct audio_stream *stream)
625{
626 uint32_t rate = proxy_get_sample_rate(&((const struct stream_in *)stream)->proxy);
627 ALOGV("in_get_sample_rate() = %d", rate);
628 return rate;
629}
630
631static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
632{
633 ALOGV("in_set_sample_rate(%d) - NOPE", rate);
634 return -ENOSYS;
635}
636
637static size_t in_get_buffer_size(const struct audio_stream *stream)
638{
639 const struct stream_in * in = ((const struct stream_in*)stream);
Paul McLean2cfd81b2014-09-15 12:32:23 -0700640 return proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700641}
642
643static uint32_t in_get_channels(const struct audio_stream *stream)
644{
Paul McLean2cfd81b2014-09-15 12:32:23 -0700645 const struct stream_in *in = (const struct stream_in*)stream;
Andy Hung780f1f82015-04-22 22:14:39 -0700646 return in->hal_channel_mask;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700647}
648
649static audio_format_t in_get_format(const struct audio_stream *stream)
650{
Andy Hung780f1f82015-04-22 22:14:39 -0700651 alsa_device_proxy *proxy = &((struct stream_in*)stream)->proxy;
652 audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
653 return format;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700654}
655
656static int in_set_format(struct audio_stream *stream, audio_format_t format)
657{
658 ALOGV("in_set_format(%d) - NOPE", format);
659
660 return -ENOSYS;
661}
662
663static int in_standby(struct audio_stream *stream)
664{
665 struct stream_in *in = (struct stream_in *)stream;
666
Eric Laurent70318092015-06-19 17:49:17 -0700667 lock_input_stream(in);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700668 if (!in->standby) {
Eric Laurent70318092015-06-19 17:49:17 -0700669 pthread_mutex_lock(&in->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700670 proxy_close(&in->proxy);
Eric Laurent70318092015-06-19 17:49:17 -0700671 pthread_mutex_unlock(&in->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700672 in->standby = true;
673 }
674
675 pthread_mutex_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700676
677 return 0;
678}
679
680static int in_dump(const struct audio_stream *stream, int fd)
681{
682 return 0;
683}
684
685static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
686{
Paul McLean65ec72b2015-02-18 09:13:24 -0800687 ALOGV("in_set_parameters() keys:%s", kvpairs);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700688
689 struct stream_in *in = (struct stream_in *)stream;
690
691 char value[32];
692 int param_val;
693 int routing = 0;
694 int ret_value = 0;
Eric Laurent05333d42014-08-04 20:29:17 -0700695 int card = -1;
696 int device = -1;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700697
Paul McLean65ec72b2015-02-18 09:13:24 -0800698 if (!parse_card_device_params(kvpairs, &card, &device)) {
699 // nothing to do
700 return ret_value;
701 }
702
Eric Laurent70318092015-06-19 17:49:17 -0700703 lock_input_stream(in);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700704 pthread_mutex_lock(&in->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700705
Paul McLean2c6196f2014-08-20 16:50:25 -0700706 if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) {
Eric Laurent05333d42014-08-04 20:29:17 -0700707 /* cannot read pcm device info if playback is active */
708 if (!in->standby)
709 ret_value = -ENOSYS;
710 else {
711 int saved_card = in->profile->card;
712 int saved_device = in->profile->device;
713 in->profile->card = card;
714 in->profile->device = device;
715 ret_value = profile_read_device_info(in->profile) ? 0 : -EINVAL;
716 if (ret_value != 0) {
717 in->profile->card = saved_card;
718 in->profile->device = saved_device;
719 }
720 }
Paul McLean2c6196f2014-08-20 16:50:25 -0700721 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700722
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700723 pthread_mutex_unlock(&in->dev->lock);
Eric Laurent70318092015-06-19 17:49:17 -0700724 pthread_mutex_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700725
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700726 return ret_value;
727}
728
729static char * in_get_parameters(const struct audio_stream *stream, const char *keys)
730{
731 struct stream_in *in = (struct stream_in *)stream;
732
Eric Laurent70318092015-06-19 17:49:17 -0700733 lock_input_stream(in);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700734 pthread_mutex_lock(&in->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700735
736 char * params_str = device_get_parameters(in->profile, keys);
737
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700738 pthread_mutex_unlock(&in->dev->lock);
Eric Laurent70318092015-06-19 17:49:17 -0700739 pthread_mutex_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700740
741 return params_str;
742}
743
744static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
745{
746 return 0;
747}
748
749static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
750{
751 return 0;
752}
753
754static int in_set_gain(struct audio_stream_in *stream, float gain)
755{
756 return 0;
757}
758
759/* must be called with hw device and output stream mutexes locked */
760static int start_input_stream(struct stream_in *in)
761{
Paul McLean65ec72b2015-02-18 09:13:24 -0800762 ALOGV("ustart_input_stream(card:%d device:%d)", in->profile->card, in->profile->device);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700763
764 return proxy_open(&in->proxy);
765}
766
767/* TODO mutex stuff here (see out_write) */
768static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
769{
770 size_t num_read_buff_bytes = 0;
771 void * read_buff = buffer;
772 void * out_buff = buffer;
Pavan Chikkala83b47a62015-01-09 12:21:13 -0800773 int ret = 0;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700774
775 struct stream_in * in = (struct stream_in *)stream;
776
Eric Laurent70318092015-06-19 17:49:17 -0700777 lock_input_stream(in);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700778 if (in->standby) {
Eric Laurent70318092015-06-19 17:49:17 -0700779 pthread_mutex_lock(&in->dev->lock);
780 ret = start_input_stream(in);
781 pthread_mutex_unlock(&in->dev->lock);
782 if (ret != 0) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700783 goto err;
784 }
785 in->standby = false;
786 }
787
788 alsa_device_profile * profile = in->profile;
789
790 /*
791 * OK, we need to figure out how much data to read to be able to output the requested
792 * number of bytes in the HAL format (16-bit, stereo).
793 */
794 num_read_buff_bytes = bytes;
Andy Hung780f1f82015-04-22 22:14:39 -0700795 int num_device_channels = proxy_get_channel_count(&in->proxy); /* what we told Alsa */
796 int num_req_channels = in->hal_channel_count; /* what we told AudioFlinger */
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700797
798 if (num_device_channels != num_req_channels) {
799 num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
800 }
801
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700802 /* Setup/Realloc the conversion buffer (if necessary). */
803 if (num_read_buff_bytes != bytes) {
804 if (num_read_buff_bytes > in->conversion_buffer_size) {
805 /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
806 (and do these conversions themselves) */
807 in->conversion_buffer_size = num_read_buff_bytes;
808 in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
809 }
810 read_buff = in->conversion_buffer;
811 }
812
Pavan Chikkala83b47a62015-01-09 12:21:13 -0800813 ret = proxy_read(&in->proxy, read_buff, num_read_buff_bytes);
814 if (ret == 0) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700815 if (num_device_channels != num_req_channels) {
816 // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels);
817
818 out_buff = buffer;
819 /* Num Channels conversion */
820 if (num_device_channels != num_req_channels) {
821 audio_format_t audio_format = in_get_format(&(in->stream.common));
822 unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
823
824 num_read_buff_bytes =
825 adjust_channels(read_buff, num_device_channels,
826 out_buff, num_req_channels,
827 sample_size_in_bytes, num_read_buff_bytes);
828 }
829 }
Eric Laurent253def92014-09-14 12:18:18 -0700830
831 /* no need to acquire in->dev->lock to read mic_muted here as we don't change its state */
832 if (num_read_buff_bytes > 0 && in->dev->mic_muted)
833 memset(buffer, 0, num_read_buff_bytes);
Viswanath L8c7e1112014-10-31 13:07:39 +0530834 } else {
Eric Laurente6499422015-01-09 17:03:27 -0800835 num_read_buff_bytes = 0; // reset the value after USB headset is unplugged
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700836 }
837
838err:
839 pthread_mutex_unlock(&in->lock);
840
841 return num_read_buff_bytes;
842}
843
844static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
845{
846 return 0;
847}
848
849static int adev_open_input_stream(struct audio_hw_device *dev,
850 audio_io_handle_t handle,
851 audio_devices_t devices,
852 struct audio_config *config,
853 struct audio_stream_in **stream_in,
Eric Laurentf5e24692014-07-27 16:14:57 -0700854 audio_input_flags_t flags __unused,
Paul McLean0f1753e2014-12-02 12:36:45 -0700855 const char *address /*__unused*/,
Eric Laurentf5e24692014-07-27 16:14:57 -0700856 audio_source_t source __unused)
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700857{
Paul McLean65ec72b2015-02-18 09:13:24 -0800858 ALOGV("in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700859 config->sample_rate, config->channel_mask, config->format);
860
861 struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
862 int ret = 0;
863
864 if (in == NULL)
865 return -ENOMEM;
866
867 /* setup function pointers */
868 in->stream.common.get_sample_rate = in_get_sample_rate;
869 in->stream.common.set_sample_rate = in_set_sample_rate;
870 in->stream.common.get_buffer_size = in_get_buffer_size;
871 in->stream.common.get_channels = in_get_channels;
872 in->stream.common.get_format = in_get_format;
873 in->stream.common.set_format = in_set_format;
874 in->stream.common.standby = in_standby;
875 in->stream.common.dump = in_dump;
876 in->stream.common.set_parameters = in_set_parameters;
877 in->stream.common.get_parameters = in_get_parameters;
878 in->stream.common.add_audio_effect = in_add_audio_effect;
879 in->stream.common.remove_audio_effect = in_remove_audio_effect;
880
881 in->stream.set_gain = in_set_gain;
882 in->stream.read = in_read;
883 in->stream.get_input_frames_lost = in_get_input_frames_lost;
884
Eric Laurent70318092015-06-19 17:49:17 -0700885 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
886 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
887
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700888 in->dev = (struct audio_device *)dev;
Paul McLean0f1753e2014-12-02 12:36:45 -0700889 pthread_mutex_lock(&in->dev->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700890
891 in->profile = &in->dev->in_profile;
892
893 struct pcm_config proxy_config;
Paul McLean2c6196f2014-08-20 16:50:25 -0700894 memset(&proxy_config, 0, sizeof(proxy_config));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700895
Paul McLean0f1753e2014-12-02 12:36:45 -0700896 /* Pull out the card/device pair */
897 parse_card_device_params(address, &(in->profile->card), &(in->profile->device));
898
899 profile_read_device_info(in->profile);
900 pthread_mutex_unlock(&in->dev->lock);
901
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700902 /* Rate */
903 if (config->sample_rate == 0) {
904 proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
905 } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) {
906 proxy_config.rate = config->sample_rate;
907 } else {
908 proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
909 ret = -EINVAL;
910 }
911
912 /* Format */
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700913 if (config->format == AUDIO_FORMAT_DEFAULT) {
Andy Hung780f1f82015-04-22 22:14:39 -0700914 proxy_config.format = profile_get_default_format(in->profile);
915 config->format = audio_format_from_pcm_format(proxy_config.format);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700916 } else {
Andy Hung780f1f82015-04-22 22:14:39 -0700917 enum pcm_format fmt = pcm_format_from_audio_format(config->format);
918 if (profile_is_format_valid(in->profile, fmt)) {
919 proxy_config.format = fmt;
920 } else {
921 proxy_config.format = profile_get_default_format(in->profile);
922 config->format = audio_format_from_pcm_format(proxy_config.format);
923 ret = -EINVAL;
924 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700925 }
926
Paul McLean2cfd81b2014-09-15 12:32:23 -0700927 /* Channels */
Andy Hung780f1f82015-04-22 22:14:39 -0700928 unsigned proposed_channel_count = 0;
Paul McLean2cfd81b2014-09-15 12:32:23 -0700929 if (k_force_channels) {
930 proposed_channel_count = k_force_channels;
Andy Hung780f1f82015-04-22 22:14:39 -0700931 } else if (config->channel_mask == AUDIO_CHANNEL_NONE) {
932 proposed_channel_count = profile_get_default_channel_count(in->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700933 }
Andy Hung780f1f82015-04-22 22:14:39 -0700934 if (proposed_channel_count != 0) {
935 config->channel_mask = audio_channel_in_mask_from_count(proposed_channel_count);
936 if (config->channel_mask == AUDIO_CHANNEL_INVALID)
937 config->channel_mask =
938 audio_channel_mask_for_index_assignment_from_count(proposed_channel_count);
939 in->hal_channel_count = proposed_channel_count;
940 } else {
941 in->hal_channel_count = audio_channel_count_from_in_mask(config->channel_mask);
942 }
943 /* we can expose any channel mask, and emulate internally based on channel count. */
944 in->hal_channel_mask = config->channel_mask;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700945
Paul McLean2cfd81b2014-09-15 12:32:23 -0700946 proxy_config.channels = profile_get_default_channel_count(in->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700947 proxy_prepare(&in->proxy, in->profile, &proxy_config);
948
949 in->standby = true;
950
951 in->conversion_buffer = NULL;
952 in->conversion_buffer_size = 0;
953
954 *stream_in = &in->stream;
955
956 return ret;
957}
958
959static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
960{
961 struct stream_in *in = (struct stream_in *)stream;
962
963 /* Close the pcm device */
964 in_standby(&stream->common);
965
966 free(in->conversion_buffer);
967
968 free(stream);
969}
970
971/*
972 * ADEV Functions
973 */
Simon Wilson19957a32012-04-06 16:17:12 -0700974static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
975{
976 return 0;
977}
978
Paul McLean30f41852014-04-16 15:44:20 -0700979static char * adev_get_parameters(const struct audio_hw_device *dev, const char *keys)
Simon Wilson19957a32012-04-06 16:17:12 -0700980{
981 return strdup("");
982}
983
984static int adev_init_check(const struct audio_hw_device *dev)
985{
986 return 0;
987}
988
989static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
990{
991 return -ENOSYS;
992}
993
994static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
995{
996 return -ENOSYS;
997}
998
999static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1000{
1001 return 0;
1002}
1003
1004static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1005{
Eric Laurent253def92014-09-14 12:18:18 -07001006 struct audio_device * adev = (struct audio_device *)dev;
1007 pthread_mutex_lock(&adev->lock);
1008 adev->mic_muted = state;
1009 pthread_mutex_unlock(&adev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -07001010 return -ENOSYS;
1011}
1012
1013static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1014{
1015 return -ENOSYS;
1016}
1017
Simon Wilson19957a32012-04-06 16:17:12 -07001018static int adev_dump(const audio_hw_device_t *device, int fd)
1019{
1020 return 0;
1021}
1022
1023static int adev_close(hw_device_t *device)
1024{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001025 struct audio_device *adev = (struct audio_device *)device;
Simon Wilson19957a32012-04-06 16:17:12 -07001026 free(device);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001027
Simon Wilson19957a32012-04-06 16:17:12 -07001028 return 0;
1029}
1030
Paul McLean30f41852014-04-16 15:44:20 -07001031static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device)
Simon Wilson19957a32012-04-06 16:17:12 -07001032{
Simon Wilson19957a32012-04-06 16:17:12 -07001033 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1034 return -EINVAL;
1035
Paul McLeaneedc92e2013-12-19 15:46:15 -08001036 struct audio_device *adev = calloc(1, sizeof(struct audio_device));
Simon Wilson19957a32012-04-06 16:17:12 -07001037 if (!adev)
1038 return -ENOMEM;
1039
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001040 profile_init(&adev->out_profile, PCM_OUT);
1041 profile_init(&adev->in_profile, PCM_IN);
1042
Simon Wilson19957a32012-04-06 16:17:12 -07001043 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent85e08e22012-08-28 14:30:35 -07001044 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001045 adev->hw_device.common.module = (struct hw_module_t *)module;
Simon Wilson19957a32012-04-06 16:17:12 -07001046 adev->hw_device.common.close = adev_close;
1047
Simon Wilson19957a32012-04-06 16:17:12 -07001048 adev->hw_device.init_check = adev_init_check;
1049 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1050 adev->hw_device.set_master_volume = adev_set_master_volume;
1051 adev->hw_device.set_mode = adev_set_mode;
1052 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1053 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1054 adev->hw_device.set_parameters = adev_set_parameters;
1055 adev->hw_device.get_parameters = adev_get_parameters;
1056 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1057 adev->hw_device.open_output_stream = adev_open_output_stream;
1058 adev->hw_device.close_output_stream = adev_close_output_stream;
1059 adev->hw_device.open_input_stream = adev_open_input_stream;
1060 adev->hw_device.close_input_stream = adev_close_input_stream;
1061 adev->hw_device.dump = adev_dump;
1062
1063 *device = &adev->hw_device.common;
1064
1065 return 0;
1066}
1067
1068static struct hw_module_methods_t hal_module_methods = {
1069 .open = adev_open,
1070};
1071
1072struct audio_module HAL_MODULE_INFO_SYM = {
1073 .common = {
1074 .tag = HARDWARE_MODULE_TAG,
Mike Lockwood46a98092012-04-24 16:41:18 -07001075 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1076 .hal_api_version = HARDWARE_HAL_API_VERSION,
Simon Wilson19957a32012-04-06 16:17:12 -07001077 .id = AUDIO_HARDWARE_MODULE_ID,
1078 .name = "USB audio HW HAL",
1079 .author = "The Android Open Source Project",
1080 .methods = &hal_module_methods,
1081 },
1082};