blob: 4af01afb0a0fcb29a0c1edf627d4d5ef1bcf7c8e [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
17#define LOG_TAG "usb_audio_hw"
Paul McLeancf611912014-04-28 13:03:18 -070018/*#define LOG_NDEBUG 0*/
Paul McLeanf62d75e2014-07-11 15:14:19 -070019/*#define LOG_PCM_PARAMS 0*/
Simon Wilson19957a32012-04-06 16:17:12 -070020
21#include <errno.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070022#include <inttypes.h>
Simon Wilson19957a32012-04-06 16:17:12 -070023#include <pthread.h>
24#include <stdint.h>
Simon Wilson19957a32012-04-06 16:17:12 -070025#include <stdlib.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070026#include <sys/time.h>
Simon Wilson19957a32012-04-06 16:17:12 -070027
Mark Salyzyn88e458a2014-04-28 12:30:44 -070028#include <log/log.h>
Simon Wilson19957a32012-04-06 16:17:12 -070029#include <cutils/str_parms.h>
30#include <cutils/properties.h>
31
Simon Wilson19957a32012-04-06 16:17:12 -070032#include <hardware/audio.h>
Paul McLeane32cbc12014-06-25 10:42:07 -070033#include <hardware/audio_alsaops.h>
34#include <hardware/hardware.h>
35
36#include <system/audio.h>
Simon Wilson19957a32012-04-06 16:17:12 -070037
38#include <tinyalsa/asoundlib.h>
39
Paul McLeanf62d75e2014-07-11 15:14:19 -070040#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
41
Paul McLeaneedc92e2013-12-19 15:46:15 -080042/* This is the default configuration to hand to The Framework on the initial
43 * adev_open_output_stream(). Actual device attributes will be used on the subsequent
44 * adev_open_output_stream() after the card and device number have been set in out_set_parameters()
45 */
46#define OUT_PERIOD_SIZE 1024
47#define OUT_PERIOD_COUNT 4
48#define OUT_SAMPLING_RATE 44100
49
50struct pcm_config default_alsa_out_config = {
Simon Wilson19957a32012-04-06 16:17:12 -070051 .channels = 2,
Paul McLeaneedc92e2013-12-19 15:46:15 -080052 .rate = OUT_SAMPLING_RATE,
53 .period_size = OUT_PERIOD_SIZE,
54 .period_count = OUT_PERIOD_COUNT,
Simon Wilson19957a32012-04-06 16:17:12 -070055 .format = PCM_FORMAT_S16_LE,
56};
57
Paul McLeaneedc92e2013-12-19 15:46:15 -080058/*
59 * Input defaults. See comment above.
60 */
61#define IN_PERIOD_SIZE 1024
62#define IN_PERIOD_COUNT 4
63#define IN_SAMPLING_RATE 44100
64
65struct pcm_config default_alsa_in_config = {
66 .channels = 2,
67 .rate = IN_SAMPLING_RATE,
68 .period_size = IN_PERIOD_SIZE,
69 .period_count = IN_PERIOD_COUNT,
70 .format = PCM_FORMAT_S16_LE,
71 .start_threshold = 1,
72 .stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT),
73};
74
Paul McLeanf62d75e2014-07-11 15:14:19 -070075struct audio_device_profile {
76 int card;
77 int device;
78 int direction; /* PCM_OUT or PCM_IN */
79};
80
Simon Wilson19957a32012-04-06 16:17:12 -070081struct audio_device {
82 struct audio_hw_device hw_device;
83
84 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Paul McLeaneedc92e2013-12-19 15:46:15 -080085
86 /* output */
Paul McLeanf62d75e2014-07-11 15:14:19 -070087 struct audio_device_profile out_profile;
Paul McLeaneedc92e2013-12-19 15:46:15 -080088
89 /* input */
Paul McLeanf62d75e2014-07-11 15:14:19 -070090 struct audio_device_profile in_profile;
Paul McLeaneedc92e2013-12-19 15:46:15 -080091
Simon Wilson19957a32012-04-06 16:17:12 -070092 bool standby;
93};
94
95struct stream_out {
96 struct audio_stream_out stream;
97
Paul McLeaneedc92e2013-12-19 15:46:15 -080098 pthread_mutex_t lock; /* see note below on mutex acquisition order */
99 struct pcm *pcm; /* state of the stream */
100 bool standby;
101
102 struct audio_device *dev; /* hardware information */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700103 struct audio_device_profile * profile;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800104
105 void * conversion_buffer; /* any conversions are put into here
106 * they could come from here too if
107 * there was a previous conversion */
108 size_t conversion_buffer_size; /* in bytes */
109};
110
111/*
112 * Output Configuration Cache
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700113 * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure.
Paul McLeaneedc92e2013-12-19 15:46:15 -0800114 */
115static struct pcm_config cached_output_hardware_config;
116static bool output_hardware_config_is_cached = false;
117
118struct stream_in {
119 struct audio_stream_in stream;
120
Simon Wilson19957a32012-04-06 16:17:12 -0700121 pthread_mutex_t lock; /* see note below on mutex acquisition order */
122 struct pcm *pcm;
123 bool standby;
124
125 struct audio_device *dev;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800126
Paul McLeanf62d75e2014-07-11 15:14:19 -0700127 struct audio_device_profile * profile;
128
Paul McLeaneedc92e2013-12-19 15:46:15 -0800129 struct audio_config hal_pcm_config;
130
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700131 /* this is the format the framework thinks it's using. We may need to convert from the actual
132 * (24-bit, 32-bit?) format to this theoretical (framework, probably 16-bit)
133 * format in in_read() */
134 enum pcm_format input_framework_format;
135
Paul McLeaneedc92e2013-12-19 15:46:15 -0800136// struct resampler_itfe *resampler;
137// struct resampler_buffer_provider buf_provider;
Paul McLean30f41852014-04-16 15:44:20 -0700138
Paul McLeaneedc92e2013-12-19 15:46:15 -0800139 int read_status;
Paul McLean30f41852014-04-16 15:44:20 -0700140
141 // We may need to read more data from the device in order to data reduce to 16bit, 4chan */
142 void * conversion_buffer; /* any conversions are put into here
143 * they could come from here too if
144 * there was a previous conversion */
145 size_t conversion_buffer_size; /* in bytes */
Simon Wilson19957a32012-04-06 16:17:12 -0700146};
147
Paul McLeaneedc92e2013-12-19 15:46:15 -0800148/*
Paul McLean30f41852014-04-16 15:44:20 -0700149 * Input Configuration Cache
150 * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure
151 * but that will involve changes in The Framework.
152 */
153static struct pcm_config cached_input_hardware_config;
154static bool input_hardware_config_is_cached = false;
155
156/*
Paul McLeaneedc92e2013-12-19 15:46:15 -0800157 * Utility
158 */
159/*
Paul McLeaneedc92e2013-12-19 15:46:15 -0800160 * Data Conversions
161 */
162/*
Paul McLean30f41852014-04-16 15:44:20 -0700163 * Convert a buffer of packed (3-byte) PCM24LE samples to PCM16LE samples.
164 * in_buff points to the buffer of PCM24LE samples
Paul McLeaneedc92e2013-12-19 15:46:15 -0800165 * num_in_samples size of input buffer in SAMPLES
Paul McLean30f41852014-04-16 15:44:20 -0700166 * out_buff points to the buffer to receive converted PCM16LE LE samples.
167 * returns
168 * the number of BYTES of output data.
169 * We are doing this since we *always* present to The Framework as A PCM16LE device, but need to
170 * support PCM24_3LE (24-bit, packed).
171 * NOTE:
Paul McLean30f41852014-04-16 15:44:20 -0700172 * This conversion is safe to do in-place (in_buff == out_buff).
Paul McLeane32cbc12014-06-25 10:42:07 -0700173 * TODO Move this to a utilities module.
Paul McLean30f41852014-04-16 15:44:20 -0700174 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700175static size_t convert_24_3_to_16(const unsigned char * in_buff, size_t num_in_samples,
176 short * out_buff)
177{
Paul McLean30f41852014-04-16 15:44:20 -0700178 /*
179 * Move from front to back so that the conversion can be done in-place
180 * i.e. in_buff == out_buff
181 */
182 /* we need 2 bytes in the output for every 3 bytes in the input */
183 unsigned char* dst_ptr = (unsigned char*)out_buff;
Mark Salyzyn88e458a2014-04-28 12:30:44 -0700184 const unsigned char* src_ptr = in_buff;
Paul McLean30f41852014-04-16 15:44:20 -0700185 size_t src_smpl_index;
186 for (src_smpl_index = 0; src_smpl_index < num_in_samples; src_smpl_index++) {
187 src_ptr++; /* lowest-(skip)-byte */
188 *dst_ptr++ = *src_ptr++; /* low-byte */
189 *dst_ptr++ = *src_ptr++; /* high-byte */
190 }
191
192 /* return number of *bytes* generated: */
193 return num_in_samples * 2;
194}
195
196/*
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700197 * Convert a buffer of packed (3-byte) PCM32 samples to PCM16LE samples.
198 * in_buff points to the buffer of PCM32 samples
199 * num_in_samples size of input buffer in SAMPLES
200 * out_buff points to the buffer to receive converted PCM16LE LE samples.
201 * returns
202 * the number of BYTES of output data.
203 * We are doing this since we *always* present to The Framework as A PCM16LE device, but need to
204 * support PCM_FORMAT_S32_LE (32-bit).
205 * NOTE:
206 * This conversion is safe to do in-place (in_buff == out_buff).
207 * TODO Move this to a utilities module.
208 */
209static size_t convert_32_to_16(const int32_t * in_buff, size_t num_in_samples, short * out_buff)
210{
211 /*
212 * Move from front to back so that the conversion can be done in-place
213 * i.e. in_buff == out_buff
214 */
215
216 short * dst_ptr = out_buff;
217 const int32_t* src_ptr = in_buff;
218 size_t src_smpl_index;
219 for (src_smpl_index = 0; src_smpl_index < num_in_samples; src_smpl_index++) {
220 *dst_ptr++ = *src_ptr++ >> 16;
221 }
222
223 /* return number of *bytes* generated: */
224 return num_in_samples * 2;
225}
226
227/*
Paul McLean30f41852014-04-16 15:44:20 -0700228 * Convert a buffer of N-channel, interleaved PCM16 samples to M-channel PCM16 channels
229 * (where N < M).
230 * in_buff points to the buffer of PCM16 samples
231 * in_buff_channels Specifies the number of channels in the input buffer.
Paul McLeaneedc92e2013-12-19 15:46:15 -0800232 * out_buff points to the buffer to receive converted PCM16 samples.
Paul McLean30f41852014-04-16 15:44:20 -0700233 * out_buff_channels Specifies the number of channels in the output buffer.
Paul McLeaneb192972014-07-11 16:29:41 -0700234 * num_in_bytes size of input buffer in BYTES
Paul McLean30f41852014-04-16 15:44:20 -0700235 * returns
236 * the number of BYTES of output data.
237 * NOTE
238 * channels > N are filled with silence.
239 * This conversion is safe to do in-place (in_buff == out_buff)
Paul McLeaneedc92e2013-12-19 15:46:15 -0800240 * We are doing this since we *always* present to The Framework as STEREO device, but need to
241 * support 4-channel devices.
Paul McLeane32cbc12014-06-25 10:42:07 -0700242 * TODO Move this to a utilities module.
Paul McLeaneedc92e2013-12-19 15:46:15 -0800243 */
Paul McLeaneb192972014-07-11 16:29:41 -0700244static size_t expand_channels_16(const int16_t* in_buff, int in_buff_chans,
245 int16_t* out_buff, int out_buff_chans,
246 size_t num_in_bytes)
Paul McLeane32cbc12014-06-25 10:42:07 -0700247{
Paul McLeaneedc92e2013-12-19 15:46:15 -0800248 /*
249 * Move from back to front so that the conversion can be done in-place
250 * i.e. in_buff == out_buff
Paul McLean30f41852014-04-16 15:44:20 -0700251 * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
Paul McLeaneedc92e2013-12-19 15:46:15 -0800252 */
Paul McLeaneb192972014-07-11 16:29:41 -0700253 size_t num_in_samples = num_in_bytes / sizeof(int16_t);
254
255 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
Paul McLean30f41852014-04-16 15:44:20 -0700256
257 short* dst_ptr = out_buff + num_out_samples - 1;
Mark Salyzyn88e458a2014-04-28 12:30:44 -0700258 size_t src_index;
259 const short* src_ptr = in_buff + num_in_samples - 1;
Paul McLean30f41852014-04-16 15:44:20 -0700260 int num_zero_chans = out_buff_chans - in_buff_chans;
261 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
262 int dst_offset;
Paul McLeane32cbc12014-06-25 10:42:07 -0700263 for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) {
Paul McLean30f41852014-04-16 15:44:20 -0700264 *dst_ptr-- = 0;
265 }
Paul McLeane32cbc12014-06-25 10:42:07 -0700266 for (; dst_offset < out_buff_chans; dst_offset++) {
Paul McLean30f41852014-04-16 15:44:20 -0700267 *dst_ptr-- = *src_ptr--;
268 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800269 }
270
271 /* return number of *bytes* generated */
Paul McLeaneb192972014-07-11 16:29:41 -0700272 return num_out_samples * sizeof(int16_t);
Paul McLean30f41852014-04-16 15:44:20 -0700273}
274
275/*
276 * Convert a buffer of N-channel, interleaved PCM16 samples to M-channel PCM16 channels
277 * (where N > M).
278 * in_buff points to the buffer of PCM16 samples
279 * in_buff_channels Specifies the number of channels in the input buffer.
280 * out_buff points to the buffer to receive converted PCM16 samples.
281 * out_buff_channels Specifies the number of channels in the output buffer.
Paul McLeaneb192972014-07-11 16:29:41 -0700282 * num_in_bytes size of input buffer in BYTES
Paul McLean30f41852014-04-16 15:44:20 -0700283 * returns
284 * the number of BYTES of output data.
285 * NOTE
286 * channels > N are thrown away.
287 * This conversion is safe to do in-place (in_buff == out_buff)
288 * We are doing this since we *always* present to The Framework as STEREO device, but need to
289 * support 4-channel devices.
Paul McLeane32cbc12014-06-25 10:42:07 -0700290 * TODO Move this to a utilities module.
Paul McLean30f41852014-04-16 15:44:20 -0700291 */
Paul McLeaneb192972014-07-11 16:29:41 -0700292static size_t contract_channels_16(const int16_t* in_buff, size_t in_buff_chans,
293 int16_t* out_buff, size_t out_buff_chans,
294 size_t num_in_bytes)
Paul McLeane32cbc12014-06-25 10:42:07 -0700295{
Paul McLean30f41852014-04-16 15:44:20 -0700296 /*
297 * Move from front to back so that the conversion can be done in-place
298 * i.e. in_buff == out_buff
299 * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
300 */
Paul McLeaneb192972014-07-11 16:29:41 -0700301 size_t num_in_samples = num_in_bytes / sizeof(int16_t);
Paul McLean30f41852014-04-16 15:44:20 -0700302
Paul McLeaneb192972014-07-11 16:29:41 -0700303 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
Paul McLean30f41852014-04-16 15:44:20 -0700304
Paul McLeaneb192972014-07-11 16:29:41 -0700305 size_t num_skip_samples = in_buff_chans - out_buff_chans;
306
307 int16_t* dst_ptr = out_buff;
308 const int16_t* src_ptr = in_buff;
Mark Salyzyn88e458a2014-04-28 12:30:44 -0700309 size_t src_index;
Paul McLean30f41852014-04-16 15:44:20 -0700310 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
Paul McLeaneb192972014-07-11 16:29:41 -0700311 size_t dst_offset;
Paul McLeane32cbc12014-06-25 10:42:07 -0700312 for (dst_offset = 0; dst_offset < out_buff_chans; dst_offset++) {
Paul McLean30f41852014-04-16 15:44:20 -0700313 *dst_ptr++ = *src_ptr++;
314 }
315 src_ptr += num_skip_samples;
316 }
317
318 /* return number of *bytes* generated */
Paul McLeaneb192972014-07-11 16:29:41 -0700319 return num_out_samples * sizeof(int16_t);
320}
321
322/*
323 * Convert a buffer of N-channel, interleaved PCM32 samples to M-channel PCM32 channels
324 * (where N < M).
325 * in_buff points to the buffer of PCM32 samples
326 * in_buff_channels Specifies the number of channels in the input buffer.
327 * out_buff points to the buffer to receive converted PCM32 samples.
328 * out_buff_channels Specifies the number of channels in the output buffer.
329 * num_in_bytes size of input buffer in BYTES
330 * returns
331 * the number of BYTES of output data.
332 * NOTE
333 * channels > N are filled with silence.
334 * This conversion is safe to do in-place (in_buff == out_buff)
335 * We are doing this since we *always* present to The Framework as STEREO device, but need to
336 * support 4-channel devices.
337 * TODO Move this to a utilities module.
338 */
339static size_t expand_channels_32(const int32_t* in_buff, size_t in_buff_chans,
340 int32_t* out_buff, size_t out_buff_chans,
341 size_t num_in_bytes)
342{
343 /*
344 * Move from back to front so that the conversion can be done in-place
345 * i.e. in_buff == out_buff
346 * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
347 */
348 size_t num_in_samples = num_in_bytes / sizeof(int32_t);
349
350 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
351
352 int32_t* dst_ptr = out_buff + num_out_samples - 1;
353 const int32_t* src_ptr = in_buff + num_in_samples - 1;
354 size_t num_zero_chans = out_buff_chans - in_buff_chans;
355 size_t src_index;
356 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
357 size_t dst_offset;
358 for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) {
359 *dst_ptr-- = 0;
360 }
361 for (; dst_offset < out_buff_chans; dst_offset++) {
362 *dst_ptr-- = *src_ptr--;
363 }
364 }
365
366 /* return number of *bytes* generated */
367 return num_out_samples * sizeof(int32_t);
368}
369
370/*
371 * Convert a buffer of N-channel, interleaved PCM32 samples to M-channel PCM16 channels
372 * (where N > M).
373 * in_buff points to the buffer of PCM32 samples
374 * in_buff_channels Specifies the number of channels in the input buffer.
375 * out_buff points to the buffer to receive converted PCM16 samples.
376 * out_buff_channels Specifies the number of channels in the output buffer.
377 * num_in_bytes size of input buffer in BYTES
378 * returns
379 * the number of BYTES of output data.
380 * NOTE
381 * channels > N are thrown away.
382 * This conversion is safe to do in-place (in_buff == out_buff)
383 * We are doing this since we *always* present to The Framework as STEREO device, but need to
384 * support 4-channel devices.
385 * TODO Move this to a utilities module.
386 */
387static size_t contract_channels_32(const int32_t* in_buff, size_t in_buff_chans,
388 int32_t* out_buff, size_t out_buff_chans,
389 size_t num_in_bytes)
390{
391 /*
392 * Move from front to back so that the conversion can be done in-place
393 * i.e. in_buff == out_buff
394 * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
395 */
396 size_t num_in_samples = num_in_bytes / sizeof(int32_t);
397
398 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
399
400 size_t num_skip_samples = in_buff_chans - out_buff_chans;
401
402 int32_t* dst_ptr = out_buff;
403 const int32_t* src_ptr = in_buff;
404 size_t src_index;
405 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
406 size_t dst_offset;
407 for (dst_offset = 0; dst_offset < out_buff_chans; dst_offset++) {
408 *dst_ptr++ = *src_ptr++;
409 }
410 src_ptr += num_skip_samples;
411 }
412
413 /* return number of *bytes* generated */
414 return num_out_samples * sizeof(int32_t);
415}
416
417static size_t contract_channels(const void* in_buff, size_t in_buff_chans,
418 void* out_buff, size_t out_buff_chans,
419 unsigned sample_size_in_bytes, size_t num_in_bytes)
420{
421 switch (sample_size_in_bytes) {
422 case 2:
423 return contract_channels_16((const int16_t*)in_buff, in_buff_chans,
424 (int16_t*)out_buff, out_buff_chans,
425 num_in_bytes);
426
427 /* TODO - do this conversion when we have a device to test it with */
428 case 3:
429 ALOGE("24-bit channel contraction not supported.");
430 return 0;
431
432 case 4:
433 return contract_channels_32((const int32_t*)in_buff, in_buff_chans,
434 (int32_t*)out_buff, out_buff_chans,
435 num_in_bytes);
436
437 default:
438 return 0;
439 }
440}
441
442static size_t expand_channels(const void* in_buff, size_t in_buff_chans,
443 void* out_buff, size_t out_buff_chans,
444 unsigned sample_size_in_bytes, size_t num_in_bytes)
445{
446 switch (sample_size_in_bytes) {
447 case 2:
448 return expand_channels_16((const int16_t*)in_buff, in_buff_chans,
449 (int16_t*)out_buff, out_buff_chans,
450 num_in_bytes);
451
452 /* TODO - do this conversion when we have a device to test it with */
453 case 3:
454 ALOGE("24-bit channel expansion not supported.");
455 return 0;
456
457 case 4:
458 return expand_channels_32((const int32_t*)in_buff, in_buff_chans,
459 (int32_t*)out_buff, out_buff_chans,
460 num_in_bytes);
461
462 default:
463 return 0;
464 }
465}
466
467static size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
468 void* out_buff, size_t out_buff_chans,
469 unsigned sample_size_in_bytes, size_t num_in_bytes)
470{
471 if (out_buff_chans > in_buff_chans) {
472 return expand_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
473 sample_size_in_bytes, num_in_bytes);
474 } else if (out_buff_chans < in_buff_chans) {
475 return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
476 sample_size_in_bytes, num_in_bytes);
477 } else if (in_buff != out_buff) {
478 memcpy(out_buff, in_buff, num_in_bytes);
479 }
480
481 return num_in_bytes;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800482}
483
484/*
485 * ALSA Utilities
486 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700487/*TODO This table and the function that uses it should be moved to a utilities module (probably) */
Paul McLeaneedc92e2013-12-19 15:46:15 -0800488/*
Paul McLeane32cbc12014-06-25 10:42:07 -0700489 * Maps bit-positions in a pcm_mask to the corresponding AUDIO_ format string.
Paul McLeaneedc92e2013-12-19 15:46:15 -0800490 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700491static const char * const format_string_map[] = {
492 "AUDIO_FORMAT_PCM_8_BIT", /* 00 - SNDRV_PCM_FORMAT_S8 */
493 "AUDIO_FORMAT_PCM_8_BIT", /* 01 - SNDRV_PCM_FORMAT_U8 */
494 "AUDIO_FORMAT_PCM_16_BIT", /* 02 - SNDRV_PCM_FORMAT_S16_LE */
495 NULL, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
496 NULL, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
497 NULL, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
498 "AUDIO_FORMAT_PCM_24_BIT_PACKED", /* 06 - SNDRV_PCM_FORMAT_S24_LE */
499 NULL, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
500 NULL, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
501 NULL, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
502 "AUDIO_FORMAT_PCM_32_BIT", /* 10 - SNDRV_PCM_FORMAT_S32_LE */
503 NULL, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
504 NULL, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
505 NULL, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
506 "AUDIO_FORMAT_PCM_FLOAT", /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
507 NULL, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
508 NULL, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
509 NULL, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
510 NULL, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
511 NULL, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
512 NULL, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
513 NULL, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
514 NULL, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
515 NULL, /* 23 - SNDRV_PCM_FORMAT_MPEG */
516 NULL, /* 24 - SNDRV_PCM_FORMAT_GSM */
517 NULL, NULL, NULL, NULL, NULL, NULL, /* 25 -> 30 (not assigned) */
518 NULL, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
519 "AUDIO_FORMAT_PCM_24_BIT_PACKED", /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
520 NULL, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
521 NULL, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
522 NULL, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
523 NULL, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
524 NULL, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
525 NULL, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
526 NULL, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
527 NULL, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
528 NULL, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
529 NULL, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
530 NULL, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
531 NULL, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
532 NULL, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
533 NULL, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
534 NULL, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
535 NULL, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
536 NULL /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
537};
538
539/*
540 * Generate string containing a bar ("|") delimited list of AUDIO_ formats specified in
541 * the mask parameter.
542 *
543 */
544static char* get_format_str_for_mask(struct pcm_mask* mask)
Paul McLeaneedc92e2013-12-19 15:46:15 -0800545{
Paul McLeane32cbc12014-06-25 10:42:07 -0700546 char buffer[256];
547 int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
548 buffer[0] = '\0';
549
550 int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
551 int bits_per_slot = sizeof(mask->bits[0]) * 8;
552
553 const char* format_str = NULL;
554 int table_size = sizeof(format_string_map)/sizeof(format_string_map[0]);
555
556 int slot_index, bit_index, table_index;
557 table_index = 0;
558 int num_written = 0;
559 for (slot_index = 0; slot_index < num_slots; slot_index++) {
560 unsigned bit_mask = 1;
561 for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
562 if ((mask->bits[slot_index] & bit_mask) != 0) {
563 format_str = table_index < table_size
564 ? format_string_map[table_index]
565 : NULL;
566 if (format_str != NULL) {
567 if (num_written != 0) {
568 num_written += snprintf(buffer + num_written,
569 buffer_size - num_written, "|");
570 }
571 num_written += snprintf(buffer + num_written, buffer_size - num_written,
572 "%s", format_str);
573 }
574 }
575 bit_mask <<= 1;
576 table_index++;
Paul McLean30f41852014-04-16 15:44:20 -0700577 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800578 }
Paul McLeane32cbc12014-06-25 10:42:07 -0700579
580 return strdup(buffer);
581}
582
583/*
584 * Maps from bit position in pcm_mask to AUDIO_ format constants.
585 */
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700586static audio_format_t const format_value_map[] = {
Paul McLeane32cbc12014-06-25 10:42:07 -0700587 AUDIO_FORMAT_PCM_8_BIT, /* 00 - SNDRV_PCM_FORMAT_S8 */
588 AUDIO_FORMAT_PCM_8_BIT, /* 01 - SNDRV_PCM_FORMAT_U8 */
589 AUDIO_FORMAT_PCM_16_BIT, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
590 AUDIO_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
591 AUDIO_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
592 AUDIO_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700593 AUDIO_FORMAT_INVALID, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
Paul McLeane32cbc12014-06-25 10:42:07 -0700594 AUDIO_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
595 AUDIO_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
596 AUDIO_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
597 AUDIO_FORMAT_PCM_32_BIT, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
598 AUDIO_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
599 AUDIO_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
600 AUDIO_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
601 AUDIO_FORMAT_PCM_FLOAT, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
602 AUDIO_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
603 AUDIO_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
604 AUDIO_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
605 AUDIO_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
606 AUDIO_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
607 AUDIO_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
608 AUDIO_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
609 AUDIO_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
610 AUDIO_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
611 AUDIO_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
612 AUDIO_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
613 AUDIO_FORMAT_INVALID,
614 AUDIO_FORMAT_INVALID,
615 AUDIO_FORMAT_INVALID,
616 AUDIO_FORMAT_INVALID,
617 AUDIO_FORMAT_INVALID,
618 AUDIO_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700619 AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
Paul McLeane32cbc12014-06-25 10:42:07 -0700620 AUDIO_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
621 AUDIO_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
622 AUDIO_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
623 AUDIO_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
624 AUDIO_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
625 AUDIO_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
626 AUDIO_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
627 AUDIO_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
628 AUDIO_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
629 AUDIO_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
630 AUDIO_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
631 AUDIO_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
632 AUDIO_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
633 AUDIO_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
634 AUDIO_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
635 AUDIO_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
636 AUDIO_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
637};
638
Paul McLean6b1c0fe2014-07-02 07:27:41 -0700639/*
640 * Returns true if mask indicates support for PCM_16.
641 */
642static bool mask_has_pcm_16(struct pcm_mask* mask) {
643 return (mask->bits[0] & 0x0004) != 0;
644}
645
Paul McLeaneb192972014-07-11 16:29:41 -0700646static audio_format_t get_format_for_mask(struct pcm_mask* mask)
Paul McLeane32cbc12014-06-25 10:42:07 -0700647{
648 int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
649 int bits_per_slot = sizeof(mask->bits[0]) * 8;
650
651 int table_size = sizeof(format_value_map) / sizeof(format_value_map[0]);
652
653 int slot_index, bit_index, table_index;
654 table_index = 0;
655 int num_written = 0;
656 for (slot_index = 0; slot_index < num_slots; slot_index++) {
657 unsigned bit_mask = 1;
658 for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
659 if ((mask->bits[slot_index] & bit_mask) != 0) {
660 /* just return the first one */
661 return table_index < table_size
662 ? format_value_map[table_index]
663 : AUDIO_FORMAT_INVALID;
664 }
665 bit_mask <<= 1;
666 table_index++;
667 }
668 }
669
670 return AUDIO_FORMAT_INVALID;
671}
672
673/*
Paul McLeana02bc9d2014-07-16 08:40:00 -0700674 * Maps from bit position in pcm_mask to PCM_ format constants.
Paul McLeane32cbc12014-06-25 10:42:07 -0700675 */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700676static int8_t const pcm_format_value_map[] = {
Paul McLeane32cbc12014-06-25 10:42:07 -0700677 PCM_FORMAT_S8, /* 00 - SNDRV_PCM_FORMAT_S8 */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700678 PCM_FORMAT_INVALID, /* 01 - SNDRV_PCM_FORMAT_U8 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700679 PCM_FORMAT_S16_LE, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700680 PCM_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
681 PCM_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
682 PCM_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
Paul McLeane32cbc12014-06-25 10:42:07 -0700683 PCM_FORMAT_S24_3LE, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700684 PCM_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
685 PCM_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
686 PCM_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
Paul McLeane32cbc12014-06-25 10:42:07 -0700687 PCM_FORMAT_S32_LE, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700688 PCM_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
689 PCM_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
690 PCM_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
691 PCM_FORMAT_INVALID, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
692 PCM_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
693 PCM_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
694 PCM_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
695 PCM_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
696 PCM_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
697 PCM_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
698 PCM_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
699 PCM_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
700 PCM_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
701 PCM_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
702 PCM_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
703 PCM_FORMAT_INVALID,
704 PCM_FORMAT_INVALID,
705 PCM_FORMAT_INVALID,
706 PCM_FORMAT_INVALID,
707 PCM_FORMAT_INVALID,
708 PCM_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
Paul McLeane32cbc12014-06-25 10:42:07 -0700709 PCM_FORMAT_S24_3LE, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700710 PCM_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
711 PCM_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
712 PCM_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
713 PCM_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
714 PCM_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
715 PCM_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
716 PCM_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
717 PCM_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
718 PCM_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
719 PCM_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
720 PCM_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
721 PCM_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
722 PCM_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
723 PCM_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
724 PCM_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
725 PCM_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
726 PCM_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
Paul McLeane32cbc12014-06-25 10:42:07 -0700727};
728
Paul McLeaneb192972014-07-11 16:29:41 -0700729/*
730 * Scans the provided format mask and returns the first non-8 bit sample
731 * format supported by the devices.
732 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700733static int get_pcm_format_for_mask(struct pcm_mask* mask) {
734 int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
735 int bits_per_slot = sizeof(mask->bits[0]) * 8;
736
Paul McLeana02bc9d2014-07-16 08:40:00 -0700737 int table_size = ARRAY_SIZE(pcm_format_value_map);
Paul McLeane32cbc12014-06-25 10:42:07 -0700738
739 int slot_index, bit_index, table_index;
740 table_index = 0;
741 int num_written = 0;
Paul McLeaneb192972014-07-11 16:29:41 -0700742 for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
Paul McLeane32cbc12014-06-25 10:42:07 -0700743 unsigned bit_mask = 1;
Paul McLeaneb192972014-07-11 16:29:41 -0700744 for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
Paul McLeane32cbc12014-06-25 10:42:07 -0700745 if ((mask->bits[slot_index] & bit_mask) != 0) {
Paul McLeana02bc9d2014-07-16 08:40:00 -0700746 /* TODO - we don't want a low-level function to be making this decision */
Paul McLeaneb192972014-07-11 16:29:41 -0700747 if (table_index != 0) { /* Don't pick 8-bit */
748 /* just return the first one */
Paul McLeana02bc9d2014-07-16 08:40:00 -0700749 return (int)pcm_format_value_map[table_index];
Paul McLeaneb192972014-07-11 16:29:41 -0700750 }
Paul McLeane32cbc12014-06-25 10:42:07 -0700751 }
752 bit_mask <<= 1;
753 table_index++;
754 }
755 }
756
Paul McLeana02bc9d2014-07-16 08:40:00 -0700757 return PCM_FORMAT_INVALID;
Paul McLeane32cbc12014-06-25 10:42:07 -0700758}
759
Paul McLeanf62d75e2014-07-11 15:14:19 -0700760static bool test_out_sample_rate(struct audio_device_profile* dev_profile, unsigned rate) {
761 struct pcm_config local_config = cached_output_hardware_config;
762 local_config.rate = rate;
763
764 bool works = false; /* let's be pessimistic */
765 struct pcm * pcm =
766 pcm_open(dev_profile->card, dev_profile->device, dev_profile->direction, &local_config);
767
768 if (pcm != NULL) {
769 works = pcm_is_ready(pcm);
770 pcm_close(pcm);
771 }
772
773 return works;
774}
775
776/* sort these highest -> lowest */
777static const unsigned std_sample_rates[] =
778 {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
779
780static char* enum_std_sample_rates(struct audio_device_profile* dev_profile,
781 unsigned min, unsigned max)
782{
783 char buffer[128];
784 buffer[0] = '\0';
785 int buffSize = ARRAY_SIZE(buffer);
786
787 char numBuffer[32];
788
789 int numEntries = 0;
790 unsigned index;
791 for(index = 0; index < ARRAY_SIZE(std_sample_rates); index++) {
792 if (std_sample_rates[index] >= min && std_sample_rates[index] <= max &&
793 test_out_sample_rate(dev_profile, std_sample_rates[index])) {
794 if (numEntries++ != 0) {
795 strncat(buffer, "|", buffSize);
796 }
797 snprintf(numBuffer, sizeof(numBuffer), "%u", std_sample_rates[index]);
798 strncat(buffer, numBuffer, buffSize);
799 }
800 }
801
802 return strdup(buffer);
803}
804
805/*
806 * Logging
807 */
Paul McLeane32cbc12014-06-25 10:42:07 -0700808static void log_pcm_mask(const char* mask_name, struct pcm_mask* mask) {
809 char buff[512];
810 char bit_buff[32];
811 int buffSize = sizeof(buff)/sizeof(buff[0]);
812
813 buff[0] = '\0';
814
815 int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
816 int bits_per_slot = sizeof(mask->bits[0]) * 8;
817
818 int slot_index, bit_index;
819 strcat(buff, "[");
820 for (slot_index = 0; slot_index < num_slots; slot_index++) {
821 unsigned bit_mask = 1;
822 for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
823 strcat(buff, (mask->bits[slot_index] & bit_mask) != 0 ? "1" : "0");
824 bit_mask <<= 1;
825 }
826 if (slot_index < num_slots - 1) {
827 strcat(buff, ",");
828 }
829 }
830 strcat(buff, "]");
831
832 ALOGV("usb:audio_hw - %s mask:%s", mask_name, buff);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800833}
834
Paul McLeancf611912014-04-28 13:03:18 -0700835static void log_pcm_params(struct pcm_params * alsa_hw_params) {
836 ALOGV("usb:audio_hw - PCM_PARAM_SAMPLE_BITS min:%u, max:%u",
837 pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS),
838 pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS));
839 ALOGV("usb:audio_hw - PCM_PARAM_FRAME_BITS min:%u, max:%u",
840 pcm_params_get_min(alsa_hw_params, PCM_PARAM_FRAME_BITS),
841 pcm_params_get_max(alsa_hw_params, PCM_PARAM_FRAME_BITS));
Paul McLeane32cbc12014-06-25 10:42:07 -0700842 log_pcm_mask("PCM_PARAM_FORMAT", pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
843 log_pcm_mask("PCM_PARAM_SUBFORMAT", pcm_params_get_mask(alsa_hw_params, PCM_PARAM_SUBFORMAT));
Paul McLeancf611912014-04-28 13:03:18 -0700844 ALOGV("usb:audio_hw - PCM_PARAM_CHANNELS min:%u, max:%u",
845 pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
846 pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
847 ALOGV("usb:audio_hw - PCM_PARAM_RATE min:%u, max:%u",
848 pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
849 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
850 ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_TIME min:%u, max:%u",
851 pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_TIME),
852 pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_TIME));
853 ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_SIZE min:%u, max:%u",
854 pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE),
855 pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE));
856 ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_BYTES min:%u, max:%u",
857 pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_BYTES),
858 pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_BYTES));
859 ALOGV("usb:audio_hw - PCM_PARAM_PERIODS min:%u, max:%u",
860 pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS),
861 pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS));
862 ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_TIME min:%u, max:%u",
863 pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_TIME),
864 pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_TIME));
865 ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_SIZE min:%u, max:%u",
866 pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE),
867 pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_SIZE));
868 ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_BYTES min:%u, max:%u",
869 pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_BYTES),
870 pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_BYTES));
871 ALOGV("usb:audio_hw - PCM_PARAM_TICK_TIME min:%u, max:%u",
872 pcm_params_get_min(alsa_hw_params, PCM_PARAM_TICK_TIME),
873 pcm_params_get_max(alsa_hw_params, PCM_PARAM_TICK_TIME));
874}
875
Paul McLeaneedc92e2013-12-19 15:46:15 -0800876/*
Paul McLean33a6b172014-06-19 12:35:28 -0700877 * Returns the supplied value rounded up to the next even multiple of 16
878 */
879static unsigned int round_to_16_mult(unsigned int size) {
880 return (size + 15) & 0xFFFFFFF0;
881}
882
Paul McLeane32cbc12014-06-25 10:42:07 -0700883/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
Paul McLean33a6b172014-06-19 12:35:28 -0700884#define MIN_BUFF_TIME 5 /* milliseconds */
885
886/*
887 * Returns the system defined minimum period size based on the supplied sample rate
888 */
889static unsigned int calc_min_period_size(unsigned int sample_rate) {
890 unsigned int period_size = (sample_rate * MIN_BUFF_TIME) / 1000;
891 return round_to_16_mult(period_size);
892}
893
894/*
Paul McLeaneedc92e2013-12-19 15:46:15 -0800895 * Reads and decodes configuration info from the specified ALSA card/device
896 */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700897static int read_alsa_device_config(struct audio_device_profile * dev_profile,
898 struct pcm_config * config)
Paul McLeaneedc92e2013-12-19 15:46:15 -0800899{
Paul McLeanf62d75e2014-07-11 15:14:19 -0700900 ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
901 dev_profile->card, dev_profile->device, dev_profile->direction);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800902
Paul McLeanf62d75e2014-07-11 15:14:19 -0700903 if (dev_profile->card < 0 || dev_profile->device < 0) {
Paul McLeaneedc92e2013-12-19 15:46:15 -0800904 return -EINVAL;
905 }
906
Paul McLeanf62d75e2014-07-11 15:14:19 -0700907 struct pcm_params * alsa_hw_params =
908 pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800909 if (alsa_hw_params == NULL) {
910 return -EINVAL;
911 }
912
Paul McLeaneb192972014-07-11 16:29:41 -0700913 int ret = 0;
914
Paul McLeaneedc92e2013-12-19 15:46:15 -0800915 /*
916 * This Logging will be useful when testing new USB devices.
917 */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700918#ifdef LOG_PCM_PARAMS
919 log_pcm_params(alsa_hw_params);
920#endif
Paul McLeaneedc92e2013-12-19 15:46:15 -0800921
922 config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
923 config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
Paul McLean33a6b172014-06-19 12:35:28 -0700924 config->period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE);
925 /* round this up to a multiple of 16 */
926 config->period_size = round_to_16_mult(config->period_size);
927 /* make sure it is above a minimum value to minimize jitter */
928 unsigned int min_period_size = calc_min_period_size(config->rate);
929 if (config->period_size < min_period_size) {
930 config->period_size = min_period_size;
931 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800932 config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
933
Paul McLeaneb192972014-07-11 16:29:41 -0700934 int format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
Paul McLeana02bc9d2014-07-16 08:40:00 -0700935 if (format == PCM_FORMAT_INVALID) {
Paul McLeaneb192972014-07-11 16:29:41 -0700936 ret = -EINVAL;
937 } else {
938 config->format = format;
939 }
Paul McLeanf62d75e2014-07-11 15:14:19 -0700940
941 pcm_params_free(alsa_hw_params);
Paul McLeaneb192972014-07-11 16:29:41 -0700942 return ret;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800943}
944
945/*
946 * HAl Functions
947 */
Simon Wilson19957a32012-04-06 16:17:12 -0700948/**
949 * NOTE: when multiple mutexes have to be acquired, always respect the
950 * following order: hw device > out stream
951 */
952
953/* Helper functions */
Simon Wilson19957a32012-04-06 16:17:12 -0700954static uint32_t out_get_sample_rate(const struct audio_stream *stream)
955{
Paul McLeaneedc92e2013-12-19 15:46:15 -0800956 return cached_output_hardware_config.rate;
Simon Wilson19957a32012-04-06 16:17:12 -0700957}
958
959static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
960{
961 return 0;
962}
963
964static size_t out_get_buffer_size(const struct audio_stream *stream)
965{
Eric Laurentc5ae6a02014-07-02 13:45:32 -0700966 return cached_output_hardware_config.period_size *
967 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Simon Wilson19957a32012-04-06 16:17:12 -0700968}
969
970static uint32_t out_get_channels(const struct audio_stream *stream)
971{
Paul McLeaneedc92e2013-12-19 15:46:15 -0800972 // Always Stero for now. We will do *some* conversions in this HAL.
Paul McLeane32cbc12014-06-25 10:42:07 -0700973 /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
974 rewrite this to return the ACTUAL channel format */
Simon Wilson19957a32012-04-06 16:17:12 -0700975 return AUDIO_CHANNEL_OUT_STEREO;
976}
977
978static audio_format_t out_get_format(const struct audio_stream *stream)
979{
Paul McLeane32cbc12014-06-25 10:42:07 -0700980 return audio_format_from_pcm_format(cached_output_hardware_config.format);
Simon Wilson19957a32012-04-06 16:17:12 -0700981}
982
983static int out_set_format(struct audio_stream *stream, audio_format_t format)
984{
Paul McLeane32cbc12014-06-25 10:42:07 -0700985 cached_output_hardware_config.format = pcm_format_from_audio_format(format);
Simon Wilson19957a32012-04-06 16:17:12 -0700986 return 0;
987}
988
989static int out_standby(struct audio_stream *stream)
990{
991 struct stream_out *out = (struct stream_out *)stream;
992
993 pthread_mutex_lock(&out->dev->lock);
994 pthread_mutex_lock(&out->lock);
995
996 if (!out->standby) {
997 pcm_close(out->pcm);
998 out->pcm = NULL;
999 out->standby = true;
1000 }
1001
1002 pthread_mutex_unlock(&out->lock);
1003 pthread_mutex_unlock(&out->dev->lock);
1004
1005 return 0;
1006}
1007
1008static int out_dump(const struct audio_stream *stream, int fd)
1009{
1010 return 0;
1011}
1012
1013static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1014{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001015 ALOGV("usb:audio_hw::out out_set_parameters() keys:%s", kvpairs);
1016
Simon Wilson19957a32012-04-06 16:17:12 -07001017 struct stream_out *out = (struct stream_out *)stream;
Simon Wilson19957a32012-04-06 16:17:12 -07001018 struct str_parms *parms;
1019 char value[32];
Paul McLeaneedc92e2013-12-19 15:46:15 -08001020 int param_val;
Simon Wilson19957a32012-04-06 16:17:12 -07001021 int routing = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001022 int ret_value = 0;
Simon Wilson19957a32012-04-06 16:17:12 -07001023
1024 parms = str_parms_create_str(kvpairs);
Paul McLeanf62d75e2014-07-11 15:14:19 -07001025 pthread_mutex_lock(&out->dev->lock);
1026 pthread_mutex_lock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -07001027
Paul McLeaneedc92e2013-12-19 15:46:15 -08001028 bool recache_device_params = false;
1029 param_val = str_parms_get_str(parms, "card", value, sizeof(value));
1030 if (param_val >= 0) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001031 out->profile->card = atoi(value);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001032 recache_device_params = true;
1033 }
Simon Wilson19957a32012-04-06 16:17:12 -07001034
Paul McLeaneedc92e2013-12-19 15:46:15 -08001035 param_val = str_parms_get_str(parms, "device", value, sizeof(value));
1036 if (param_val >= 0) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001037 out->profile->device = atoi(value);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001038 recache_device_params = true;
1039 }
1040
Paul McLeanf62d75e2014-07-11 15:14:19 -07001041 if (recache_device_params && out->profile->card >= 0 && out->profile->device >= 0) {
1042 ret_value = read_alsa_device_config(out->profile, &cached_output_hardware_config);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001043 output_hardware_config_is_cached = (ret_value == 0);
1044 }
Simon Wilson19957a32012-04-06 16:17:12 -07001045
Paul McLeanf62d75e2014-07-11 15:14:19 -07001046 pthread_mutex_unlock(&out->lock);
1047 pthread_mutex_unlock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -07001048 str_parms_destroy(parms);
1049
Paul McLeaneedc92e2013-12-19 15:46:15 -08001050 return ret_value;
Simon Wilson19957a32012-04-06 16:17:12 -07001051}
1052
Paul McLeanf62d75e2014-07-11 15:14:19 -07001053static char * device_get_parameters(struct audio_device_profile * dev_profile, const char *keys)
Paul McLean30f41852014-04-16 15:44:20 -07001054{
Paul McLeanf62d75e2014-07-11 15:14:19 -07001055 ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
Paul McLean30f41852014-04-16 15:44:20 -07001056
Paul McLeanf62d75e2014-07-11 15:14:19 -07001057 if (dev_profile->card < 0 || dev_profile->device < 0) {
Paul McLean30f41852014-04-16 15:44:20 -07001058 return strdup("");
Paul McLeanf62d75e2014-07-11 15:14:19 -07001059 }
Paul McLean30f41852014-04-16 15:44:20 -07001060
Paul McLeaneedc92e2013-12-19 15:46:15 -08001061 unsigned min, max;
1062
1063 struct str_parms *query = str_parms_create_str(keys);
1064 struct str_parms *result = str_parms_create();
1065
1066 int num_written = 0;
1067 char buffer[256];
1068 int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
1069 char* result_str = NULL;
1070
Paul McLeanf62d75e2014-07-11 15:14:19 -07001071 struct pcm_params * alsa_hw_params =
1072 pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001073
1074 // These keys are from hardware/libhardware/include/audio.h
1075 // supported sample rates
1076 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
Paul McLeaneedc92e2013-12-19 15:46:15 -08001077 min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
1078 max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE);
Paul McLeanf62d75e2014-07-11 15:14:19 -07001079
1080 char* rates_list = enum_std_sample_rates(dev_profile, min, max);
1081 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, rates_list);
1082 free(rates_list);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001083 } // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES
1084
1085 // supported channel counts
1086 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001087 // TODO remove this hack when it is superceeded by proper multi-channel support
1088 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
1089 dev_profile->direction == PCM_OUT
1090 ? "AUDIO_CHANNEL_OUT_STEREO"
1091 : "AUDIO_CHANNEL_IN_STEREO");
Paul McLeaneedc92e2013-12-19 15:46:15 -08001092 } // AUDIO_PARAMETER_STREAM_SUP_CHANNELS
1093
1094 // supported sample formats
1095 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001096 // TODO remove this hack when we have support for input in non PCM16 formats
1097 if (dev_profile->direction == PCM_IN) {
1098 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, "AUDIO_FORMAT_PCM_16_BIT");
1099 } else {
1100 struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
1101 char * format_params = get_format_str_for_mask(format_mask);
1102 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
1103 free(format_params);
1104 }
Paul McLeaneedc92e2013-12-19 15:46:15 -08001105 } // AUDIO_PARAMETER_STREAM_SUP_FORMATS
1106
Paul McLeanf62d75e2014-07-11 15:14:19 -07001107 pcm_params_free(alsa_hw_params);
1108
Paul McLeaneedc92e2013-12-19 15:46:15 -08001109 result_str = str_parms_to_str(result);
1110
1111 // done with these...
1112 str_parms_destroy(query);
1113 str_parms_destroy(result);
1114
Paul McLeanf62d75e2014-07-11 15:14:19 -07001115 ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
Paul McLeane32cbc12014-06-25 10:42:07 -07001116
Paul McLeaneedc92e2013-12-19 15:46:15 -08001117 return result_str;
Simon Wilson19957a32012-04-06 16:17:12 -07001118}
1119
Paul McLeanf62d75e2014-07-11 15:14:19 -07001120static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1121{
1122 ALOGV("usb:audio_hw::out out_get_parameters() keys:%s", keys);
1123
1124 struct stream_out *out = (struct stream_out *) stream;
1125 pthread_mutex_lock(&out->dev->lock);
1126 pthread_mutex_lock(&out->lock);
1127
1128 char * params_str = device_get_parameters(out->profile, keys);
1129
1130 pthread_mutex_unlock(&out->lock);
1131 pthread_mutex_unlock(&out->dev->lock);
1132
1133 return params_str;
1134}
1135
Simon Wilson19957a32012-04-06 16:17:12 -07001136static uint32_t out_get_latency(const struct audio_stream_out *stream)
1137{
Paul McLeanf62d75e2014-07-11 15:14:19 -07001138 // struct stream_out *out = (struct stream_out *) stream;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001139
Paul McLeane32cbc12014-06-25 10:42:07 -07001140 /*TODO Do we need a term here for the USB latency (as reported in the USB descriptors)? */
Paul McLean30f41852014-04-16 15:44:20 -07001141 uint32_t latency = (cached_output_hardware_config.period_size
Paul McLeane32cbc12014-06-25 10:42:07 -07001142 * cached_output_hardware_config.period_count * 1000)
1143 / out_get_sample_rate(&stream->common);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001144 return latency;
Simon Wilson19957a32012-04-06 16:17:12 -07001145}
1146
Paul McLean30f41852014-04-16 15:44:20 -07001147static int out_set_volume(struct audio_stream_out *stream, float left, float right)
Simon Wilson19957a32012-04-06 16:17:12 -07001148{
1149 return -ENOSYS;
1150}
1151
Paul McLeaneedc92e2013-12-19 15:46:15 -08001152/* must be called with hw device and output stream mutexes locked */
1153static int start_output_stream(struct stream_out *out)
1154{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001155 int return_val = 0;
1156
Paul McLean30f41852014-04-16 15:44:20 -07001157 ALOGV("usb:audio_hw::out start_output_stream(card:%d device:%d)",
Paul McLeanf62d75e2014-07-11 15:14:19 -07001158 out->profile->card, out->profile->device);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001159
Paul McLeanf62d75e2014-07-11 15:14:19 -07001160 out->pcm = pcm_open(out->profile->card, out->profile->device, PCM_OUT,
1161 &cached_output_hardware_config);
Paul McLeane32cbc12014-06-25 10:42:07 -07001162
Paul McLeaneedc92e2013-12-19 15:46:15 -08001163 if (out->pcm == NULL) {
1164 return -ENOMEM;
1165 }
1166
1167 if (out->pcm && !pcm_is_ready(out->pcm)) {
1168 ALOGE("audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(out->pcm));
1169 pcm_close(out->pcm);
1170 return -ENOMEM;
1171 }
1172
Paul McLeaneedc92e2013-12-19 15:46:15 -08001173 return 0;
1174}
1175
1176static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes)
Simon Wilson19957a32012-04-06 16:17:12 -07001177{
1178 int ret;
1179 struct stream_out *out = (struct stream_out *)stream;
1180
1181 pthread_mutex_lock(&out->dev->lock);
1182 pthread_mutex_lock(&out->lock);
1183 if (out->standby) {
1184 ret = start_output_stream(out);
1185 if (ret != 0) {
1186 goto err;
1187 }
1188 out->standby = false;
1189 }
1190
Paul McLean30f41852014-04-16 15:44:20 -07001191 // Setup conversion buffer
1192 // compute maximum potential buffer size.
1193 // * 2 for stereo -> quad conversion
1194 // * 3/2 for 16bit -> 24 bit conversion
Mark Salyzyn88e458a2014-04-28 12:30:44 -07001195 size_t required_conversion_buffer_size = (bytes * 3 * 2) / 2;
Paul McLean30f41852014-04-16 15:44:20 -07001196 if (required_conversion_buffer_size > out->conversion_buffer_size) {
Paul McLeane32cbc12014-06-25 10:42:07 -07001197 /* TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
1198 (and do these conversions themselves) */
Paul McLean30f41852014-04-16 15:44:20 -07001199 out->conversion_buffer_size = required_conversion_buffer_size;
1200 out->conversion_buffer = realloc(out->conversion_buffer, out->conversion_buffer_size);
1201 }
1202
Mark Salyzyn88e458a2014-04-28 12:30:44 -07001203 const void * write_buff = buffer;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001204 int num_write_buff_bytes = bytes;
1205
1206 /*
1207 * Num Channels conversion
1208 */
1209 int num_device_channels = cached_output_hardware_config.channels;
1210 int num_req_channels = 2; /* always, for now */
Paul McLean30f41852014-04-16 15:44:20 -07001211 if (num_device_channels != num_req_channels) {
Paul McLeaneb192972014-07-11 16:29:41 -07001212 audio_format_t audio_format = out_get_format(&(out->stream.common));
1213 unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001214 num_write_buff_bytes =
Paul McLeaneb192972014-07-11 16:29:41 -07001215 adjust_channels(write_buff, num_req_channels,
1216 out->conversion_buffer, num_device_channels,
1217 sample_size_in_bytes, num_write_buff_bytes);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001218 write_buff = out->conversion_buffer;
1219 }
1220
Paul McLeaneedc92e2013-12-19 15:46:15 -08001221 if (write_buff != NULL && num_write_buff_bytes != 0) {
1222 pcm_write(out->pcm, write_buff, num_write_buff_bytes);
1223 }
Simon Wilson19957a32012-04-06 16:17:12 -07001224
1225 pthread_mutex_unlock(&out->lock);
1226 pthread_mutex_unlock(&out->dev->lock);
1227
1228 return bytes;
1229
1230err:
1231 pthread_mutex_unlock(&out->lock);
Amit Shekharf9953b72014-01-30 12:47:34 -08001232 pthread_mutex_unlock(&out->dev->lock);
Simon Wilson19957a32012-04-06 16:17:12 -07001233 if (ret != 0) {
Eric Laurentc5ae6a02014-07-02 13:45:32 -07001234 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Simon Wilson19957a32012-04-06 16:17:12 -07001235 out_get_sample_rate(&stream->common));
1236 }
1237
1238 return bytes;
1239}
1240
Paul McLean30f41852014-04-16 15:44:20 -07001241static int out_get_render_position(const struct audio_stream_out *stream, uint32_t *dsp_frames)
Simon Wilson19957a32012-04-06 16:17:12 -07001242{
1243 return -EINVAL;
1244}
1245
1246static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1247{
1248 return 0;
1249}
1250
1251static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1252{
1253 return 0;
1254}
1255
Paul McLean30f41852014-04-16 15:44:20 -07001256static int out_get_next_write_timestamp(const struct audio_stream_out *stream, int64_t *timestamp)
Simon Wilson19957a32012-04-06 16:17:12 -07001257{
1258 return -EINVAL;
1259}
1260
1261static int adev_open_output_stream(struct audio_hw_device *dev,
Mike Lockwood46a98092012-04-24 16:41:18 -07001262 audio_io_handle_t handle,
1263 audio_devices_t devices,
1264 audio_output_flags_t flags,
1265 struct audio_config *config,
Simon Wilson19957a32012-04-06 16:17:12 -07001266 struct audio_stream_out **stream_out)
1267{
Paul McLean30f41852014-04-16 15:44:20 -07001268 ALOGV("usb:audio_hw::out adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X",
Paul McLeaneedc92e2013-12-19 15:46:15 -08001269 handle, devices, flags);
1270
Simon Wilson19957a32012-04-06 16:17:12 -07001271 struct audio_device *adev = (struct audio_device *)dev;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001272
Simon Wilson19957a32012-04-06 16:17:12 -07001273 struct stream_out *out;
Simon Wilson19957a32012-04-06 16:17:12 -07001274
1275 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1276 if (!out)
1277 return -ENOMEM;
1278
Paul McLeaneedc92e2013-12-19 15:46:15 -08001279 // setup function pointers
Simon Wilson19957a32012-04-06 16:17:12 -07001280 out->stream.common.get_sample_rate = out_get_sample_rate;
1281 out->stream.common.set_sample_rate = out_set_sample_rate;
1282 out->stream.common.get_buffer_size = out_get_buffer_size;
1283 out->stream.common.get_channels = out_get_channels;
1284 out->stream.common.get_format = out_get_format;
1285 out->stream.common.set_format = out_set_format;
1286 out->stream.common.standby = out_standby;
1287 out->stream.common.dump = out_dump;
1288 out->stream.common.set_parameters = out_set_parameters;
1289 out->stream.common.get_parameters = out_get_parameters;
1290 out->stream.common.add_audio_effect = out_add_audio_effect;
1291 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1292 out->stream.get_latency = out_get_latency;
1293 out->stream.set_volume = out_set_volume;
1294 out->stream.write = out_write;
1295 out->stream.get_render_position = out_get_render_position;
1296 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1297
1298 out->dev = adev;
1299
Paul McLeanf62d75e2014-07-11 15:14:19 -07001300 out->profile = &(adev->out_profile);
1301 out->profile->direction = PCM_OUT;
1302
Paul McLeaneedc92e2013-12-19 15:46:15 -08001303 if (output_hardware_config_is_cached) {
1304 config->sample_rate = cached_output_hardware_config.rate;
1305
Paul McLeane32cbc12014-06-25 10:42:07 -07001306 config->format = audio_format_from_pcm_format(cached_output_hardware_config.format);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001307
1308 config->channel_mask =
1309 audio_channel_out_mask_from_count(cached_output_hardware_config.channels);
1310 if (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO) {
1311 // Always report STEREO for now. AudioPolicyManagerBase/AudioFlinger dont' understand
1312 // formats with more channels, so we won't get chosen (say with a 4-channel DAC).
Paul McLeane32cbc12014-06-25 10:42:07 -07001313 /*TODO remove this when the above restriction is removed. */
Paul McLeaneedc92e2013-12-19 15:46:15 -08001314 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1315 }
1316 } else {
1317 cached_output_hardware_config = default_alsa_out_config;
1318
1319 config->format = out_get_format(&out->stream.common);
1320 config->channel_mask = out_get_channels(&out->stream.common);
1321 config->sample_rate = out_get_sample_rate(&out->stream.common);
1322 }
Paul McLeaneedc92e2013-12-19 15:46:15 -08001323
1324 out->conversion_buffer = NULL;
1325 out->conversion_buffer_size = 0;
Simon Wilson19957a32012-04-06 16:17:12 -07001326
1327 out->standby = true;
1328
1329 *stream_out = &out->stream;
1330 return 0;
1331
1332err_open:
1333 free(out);
1334 *stream_out = NULL;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001335 return -ENOSYS;
Simon Wilson19957a32012-04-06 16:17:12 -07001336}
1337
1338static void adev_close_output_stream(struct audio_hw_device *dev,
1339 struct audio_stream_out *stream)
1340{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001341 ALOGV("usb:audio_hw::out adev_close_output_stream()");
Simon Wilson19957a32012-04-06 16:17:12 -07001342 struct stream_out *out = (struct stream_out *)stream;
1343
Paul McLeane32cbc12014-06-25 10:42:07 -07001344 // Close the pcm device
Simon Wilson19957a32012-04-06 16:17:12 -07001345 out_standby(&stream->common);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001346
1347 free(out->conversion_buffer);
1348 out->conversion_buffer = NULL;
1349 out->conversion_buffer_size = 0;
1350
Simon Wilson19957a32012-04-06 16:17:12 -07001351 free(stream);
1352}
1353
1354static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1355{
1356 return 0;
1357}
1358
Paul McLean30f41852014-04-16 15:44:20 -07001359static char * adev_get_parameters(const struct audio_hw_device *dev, const char *keys)
Simon Wilson19957a32012-04-06 16:17:12 -07001360{
1361 return strdup("");
1362}
1363
1364static int adev_init_check(const struct audio_hw_device *dev)
1365{
1366 return 0;
1367}
1368
1369static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1370{
1371 return -ENOSYS;
1372}
1373
1374static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1375{
1376 return -ENOSYS;
1377}
1378
1379static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1380{
1381 return 0;
1382}
1383
1384static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1385{
1386 return -ENOSYS;
1387}
1388
1389static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1390{
1391 return -ENOSYS;
1392}
1393
1394static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Mike Lockwood46a98092012-04-24 16:41:18 -07001395 const struct audio_config *config)
Simon Wilson19957a32012-04-06 16:17:12 -07001396{
1397 return 0;
1398}
1399
Paul McLeaneedc92e2013-12-19 15:46:15 -08001400/* Helper functions */
1401static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1402{
Paul McLean30f41852014-04-16 15:44:20 -07001403 return cached_input_hardware_config.rate;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001404}
1405
1406static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1407{
1408 return -ENOSYS;
1409}
1410
1411static size_t in_get_buffer_size(const struct audio_stream *stream)
1412{
Eric Laurentc5ae6a02014-07-02 13:45:32 -07001413 size_t buffer_size = cached_input_hardware_config.period_size *
1414 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
1415 ALOGV("usb: in_get_buffer_size() = %zu", buffer_size);
1416 return buffer_size;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001417}
1418
1419static uint32_t in_get_channels(const struct audio_stream *stream)
1420{
Paul McLean30f41852014-04-16 15:44:20 -07001421 // just report stereo for now
1422 return AUDIO_CHANNEL_IN_STEREO;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001423}
1424
1425static audio_format_t in_get_format(const struct audio_stream *stream)
1426{
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001427 const struct stream_in * in_stream = (const struct stream_in *)stream;
1428
1429 ALOGV("in_get_format() = %d -> %d", in_stream->input_framework_format,
1430 audio_format_from_pcm_format(in_stream->input_framework_format));
1431 /* return audio_format_from_pcm_format(cached_input_hardware_config.format); */
1432 return audio_format_from_pcm_format(in_stream->input_framework_format);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001433}
1434
1435static int in_set_format(struct audio_stream *stream, audio_format_t format)
1436{
1437 return -ENOSYS;
1438}
1439
1440static int in_standby(struct audio_stream *stream)
1441{
Paul McLean30f41852014-04-16 15:44:20 -07001442 struct stream_in *in = (struct stream_in *) stream;
1443
1444 pthread_mutex_lock(&in->dev->lock);
1445 pthread_mutex_lock(&in->lock);
1446
1447 if (!in->standby) {
1448 pcm_close(in->pcm);
1449 in->pcm = NULL;
1450 in->standby = true;
1451 }
1452
1453 pthread_mutex_unlock(&in->lock);
1454 pthread_mutex_unlock(&in->dev->lock);
1455
Paul McLeaneedc92e2013-12-19 15:46:15 -08001456 return 0;
1457}
1458
1459static int in_dump(const struct audio_stream *stream, int fd)
1460{
1461 return 0;
1462}
1463
1464static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1465{
Paul McLean30f41852014-04-16 15:44:20 -07001466 ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001467
1468 struct stream_in *in = (struct stream_in *)stream;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001469 struct str_parms *parms;
1470 char value[32];
1471 int param_val;
1472 int routing = 0;
1473 int ret_value = 0;
1474
1475 parms = str_parms_create_str(kvpairs);
Paul McLeanf62d75e2014-07-11 15:14:19 -07001476 pthread_mutex_lock(&in->dev->lock);
1477 pthread_mutex_lock(&in->lock);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001478
Paul McLean30f41852014-04-16 15:44:20 -07001479 bool recache_device_params = false;
1480
Paul McLeaneedc92e2013-12-19 15:46:15 -08001481 // Card/Device
1482 param_val = str_parms_get_str(parms, "card", value, sizeof(value));
1483 if (param_val >= 0) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001484 in->profile->card = atoi(value);
Paul McLean30f41852014-04-16 15:44:20 -07001485 recache_device_params = true;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001486 }
1487
1488 param_val = str_parms_get_str(parms, "device", value, sizeof(value));
1489 if (param_val >= 0) {
Paul McLeanf62d75e2014-07-11 15:14:19 -07001490 in->profile->device = atoi(value);
Paul McLean30f41852014-04-16 15:44:20 -07001491 recache_device_params = true;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001492 }
1493
Paul McLeanf62d75e2014-07-11 15:14:19 -07001494 if (recache_device_params && in->profile->card >= 0 && in->profile->device >= 0) {
1495 ret_value = read_alsa_device_config(in->profile, &cached_input_hardware_config);
Paul McLean30f41852014-04-16 15:44:20 -07001496 input_hardware_config_is_cached = (ret_value == 0);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001497 }
1498
Paul McLeanf62d75e2014-07-11 15:14:19 -07001499 pthread_mutex_unlock(&in->lock);
1500 pthread_mutex_unlock(&in->dev->lock);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001501 str_parms_destroy(parms);
1502
1503 return ret_value;
1504}
1505
Paul McLean30f41852014-04-16 15:44:20 -07001506static char * in_get_parameters(const struct audio_stream *stream, const char *keys) {
1507 ALOGV("usb:audio_hw::in in_get_parameters() keys:%s", keys);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001508
Paul McLean30f41852014-04-16 15:44:20 -07001509 struct stream_in *in = (struct stream_in *)stream;
Paul McLeanf62d75e2014-07-11 15:14:19 -07001510 pthread_mutex_lock(&in->dev->lock);
1511 pthread_mutex_lock(&in->lock);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001512
Paul McLeanf62d75e2014-07-11 15:14:19 -07001513 char * params_str = device_get_parameters(in->profile, keys);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001514
Paul McLeanf62d75e2014-07-11 15:14:19 -07001515 pthread_mutex_unlock(&in->lock);
1516 pthread_mutex_unlock(&in->dev->lock);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001517
Paul McLeanf62d75e2014-07-11 15:14:19 -07001518 return params_str;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001519}
1520
1521static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1522{
1523 return 0;
1524}
1525
1526static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1527{
1528 return 0;
1529}
1530
Paul McLean30f41852014-04-16 15:44:20 -07001531static int in_set_gain(struct audio_stream_in *stream, float gain)
1532{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001533 return 0;
1534}
1535
Paul McLean30f41852014-04-16 15:44:20 -07001536/* must be called with hw device and output stream mutexes locked */
1537static int start_input_stream(struct stream_in *in) {
Paul McLean30f41852014-04-16 15:44:20 -07001538 int return_val = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001539
Paul McLean30f41852014-04-16 15:44:20 -07001540 ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
Paul McLeanf62d75e2014-07-11 15:14:19 -07001541 in->profile->card, in->profile->device);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001542
Paul McLeanf62d75e2014-07-11 15:14:19 -07001543 in->pcm = pcm_open(in->profile->card, in->profile->device, PCM_IN,
1544 &cached_input_hardware_config);
Paul McLean30f41852014-04-16 15:44:20 -07001545 if (in->pcm == NULL) {
1546 ALOGE("usb:audio_hw pcm_open() in->pcm == NULL");
1547 return -ENOMEM;
1548 }
1549
1550 if (in->pcm && !pcm_is_ready(in->pcm)) {
1551 ALOGE("usb:audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(in->pcm));
1552 pcm_close(in->pcm);
1553 return -ENOMEM;
1554 }
1555
1556 return 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001557}
1558
Paul McLeane32cbc12014-06-25 10:42:07 -07001559/* TODO mutex stuff here (see out_write) */
Paul McLean30f41852014-04-16 15:44:20 -07001560static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
1561{
Mark Salyzyn88e458a2014-04-28 12:30:44 -07001562 size_t num_read_buff_bytes = 0;
Paul McLean30f41852014-04-16 15:44:20 -07001563 void * read_buff = buffer;
1564 void * out_buff = buffer;
1565
1566 struct stream_in * in = (struct stream_in *) stream;
1567
1568 pthread_mutex_lock(&in->dev->lock);
1569 pthread_mutex_lock(&in->lock);
1570
1571 if (in->standby) {
1572 if (start_input_stream(in) != 0) {
1573 goto err;
1574 }
1575 in->standby = false;
1576 }
1577
1578 // OK, we need to figure out how much data to read to be able to output the requested
1579 // number of bytes in the HAL format (16-bit, stereo).
1580 num_read_buff_bytes = bytes;
1581 int num_device_channels = cached_input_hardware_config.channels;
1582 int num_req_channels = 2; /* always, for now */
1583
1584 if (num_device_channels != num_req_channels) {
Paul McLeancf611912014-04-28 13:03:18 -07001585 num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
Paul McLean30f41852014-04-16 15:44:20 -07001586 }
1587
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001588 /* Assume (for now) that in->input_framework_format == PCM_FORMAT_S16_LE */
Eric Laurent7661a482014-06-11 12:00:16 -07001589 if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001590 /* 24-bit USB device */
Paul McLean30f41852014-04-16 15:44:20 -07001591 num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001592 } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
1593 /* 32-bit USB device */
1594 num_read_buff_bytes = num_read_buff_bytes * 2;
Paul McLean30f41852014-04-16 15:44:20 -07001595 }
1596
1597 // Setup/Realloc the conversion buffer (if necessary).
1598 if (num_read_buff_bytes != bytes) {
1599 if (num_read_buff_bytes > in->conversion_buffer_size) {
Paul McLeane32cbc12014-06-25 10:42:07 -07001600 /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
1601 (and do these conversions themselves) */
Paul McLean30f41852014-04-16 15:44:20 -07001602 in->conversion_buffer_size = num_read_buff_bytes;
1603 in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
1604 }
1605 read_buff = in->conversion_buffer;
1606 }
1607
1608 if (pcm_read(in->pcm, read_buff, num_read_buff_bytes) == 0) {
1609 /*
1610 * Do any conversions necessary to send the data in the format specified to/by the HAL
1611 * (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
1612 */
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001613 if (cached_input_hardware_config.format != PCM_FORMAT_S16_LE) {
1614 // we need to convert
Paul McLean30f41852014-04-16 15:44:20 -07001615 if (num_device_channels != num_req_channels) {
1616 out_buff = read_buff;
1617 }
1618
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001619 if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
1620 num_read_buff_bytes =
1621 convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
1622 } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
1623 num_read_buff_bytes =
1624 convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
1625 }
1626 else {
1627 goto err;
1628 }
Paul McLean30f41852014-04-16 15:44:20 -07001629 }
1630
1631 if (num_device_channels != num_req_channels) {
1632 out_buff = buffer;
1633 /* Num Channels conversion */
Paul McLeaneb192972014-07-11 16:29:41 -07001634 if (num_device_channels != num_req_channels) {
1635 audio_format_t audio_format = in_get_format(&(in->stream.common));
1636 unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
1637
Paul McLeancf611912014-04-28 13:03:18 -07001638 num_read_buff_bytes =
Paul McLeaneb192972014-07-11 16:29:41 -07001639 adjust_channels(read_buff, num_device_channels,
1640 out_buff, num_req_channels,
1641 sample_size_in_bytes, num_read_buff_bytes);
Paul McLeancf611912014-04-28 13:03:18 -07001642 }
Paul McLean30f41852014-04-16 15:44:20 -07001643 }
1644 }
1645
1646err:
1647 pthread_mutex_unlock(&in->lock);
1648 pthread_mutex_unlock(&in->dev->lock);
1649
1650 return num_read_buff_bytes;
1651}
1652
1653static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1654{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001655 return 0;
1656}
1657
Mike Lockwood46a98092012-04-24 16:41:18 -07001658static int adev_open_input_stream(struct audio_hw_device *dev,
1659 audio_io_handle_t handle,
1660 audio_devices_t devices,
Paul McLean30f41852014-04-16 15:44:20 -07001661 struct audio_config *config,
Simon Wilson19957a32012-04-06 16:17:12 -07001662 struct audio_stream_in **stream_in)
1663{
Mark Salyzyn88e458a2014-04-28 12:30:44 -07001664 ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
Paul McLean30f41852014-04-16 15:44:20 -07001665 config->sample_rate, config->channel_mask, config->format);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001666
1667 struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Eric Laurent7661a482014-06-11 12:00:16 -07001668 int ret = 0;
1669
Paul McLeaneedc92e2013-12-19 15:46:15 -08001670 if (in == NULL)
1671 return -ENOMEM;
1672
1673 // setup function pointers
1674 in->stream.common.get_sample_rate = in_get_sample_rate;
1675 in->stream.common.set_sample_rate = in_set_sample_rate;
1676 in->stream.common.get_buffer_size = in_get_buffer_size;
1677 in->stream.common.get_channels = in_get_channels;
1678 in->stream.common.get_format = in_get_format;
1679 in->stream.common.set_format = in_set_format;
1680 in->stream.common.standby = in_standby;
1681 in->stream.common.dump = in_dump;
1682 in->stream.common.set_parameters = in_set_parameters;
1683 in->stream.common.get_parameters = in_get_parameters;
1684 in->stream.common.add_audio_effect = in_add_audio_effect;
1685 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1686
1687 in->stream.set_gain = in_set_gain;
1688 in->stream.read = in_read;
1689 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1690
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001691 in->input_framework_format = PCM_FORMAT_S16_LE;
1692
Paul McLean30f41852014-04-16 15:44:20 -07001693 in->dev = (struct audio_device *)dev;
1694
Paul McLeanf62d75e2014-07-11 15:14:19 -07001695 in->profile = &(in->dev->in_profile);
1696 in->profile->direction = PCM_IN;
1697
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001698 if (!input_hardware_config_is_cached) {
1699 // just return defaults until we can actually query the device.
Paul McLean30f41852014-04-16 15:44:20 -07001700 cached_input_hardware_config = default_alsa_in_config;
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001701 }
Paul McLean30f41852014-04-16 15:44:20 -07001702
Paul McLean6b1c0fe2014-07-02 07:27:41 -07001703 /* Rate */
1704 /* TODO Check that the requested rate is valid for the connected device */
1705 if (config->sample_rate == 0) {
1706 config->sample_rate = cached_input_hardware_config.rate;
1707 } else {
1708 cached_input_hardware_config.rate = config->sample_rate;
1709 }
1710
1711 /* Format */
1712 /* until the framework supports format conversion, just take what it asks for
1713 * i.e. AUDIO_FORMAT_PCM_16_BIT */
1714 /* config->format = audio_format_from_pcm_format(cached_input_hardware_config.format); */
1715 if (config->format == AUDIO_FORMAT_DEFAULT) {
1716 /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
1717 * formats */
1718 config->format = AUDIO_FORMAT_PCM_16_BIT;
1719 } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
1720 /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
1721 * formats */
1722 } else {
1723 /* When the framework support other formats, validate here */
1724 config->format = AUDIO_FORMAT_PCM_16_BIT;
1725 ret = -EINVAL;
1726 }
1727
1728 /* don't change the cached_input_hardware_config, we will open it as what it is and
1729 * convert as necessary */
1730 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
1731 /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
1732 * formats */
1733 config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
1734 } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
1735 /* allow only stereo capture for now */
1736 config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
1737 ret = -EINVAL;
Paul McLean30f41852014-04-16 15:44:20 -07001738 }
Paul McLeaneedc92e2013-12-19 15:46:15 -08001739
1740 in->standby = true;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001741
Paul McLean30f41852014-04-16 15:44:20 -07001742 in->conversion_buffer = NULL;
1743 in->conversion_buffer_size = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001744
1745 *stream_in = &in->stream;
1746
Eric Laurent7661a482014-06-11 12:00:16 -07001747 return ret;
Simon Wilson19957a32012-04-06 16:17:12 -07001748}
1749
Paul McLean30f41852014-04-16 15:44:20 -07001750static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
Simon Wilson19957a32012-04-06 16:17:12 -07001751{
Paul McLean30f41852014-04-16 15:44:20 -07001752 struct stream_in *in = (struct stream_in *)stream;
1753
Paul McLeane32cbc12014-06-25 10:42:07 -07001754 // Close the pcm device
Paul McLean30f41852014-04-16 15:44:20 -07001755 in_standby(&stream->common);
1756
1757 free(in->conversion_buffer);
1758
1759 free(stream);
Simon Wilson19957a32012-04-06 16:17:12 -07001760}
1761
1762static int adev_dump(const audio_hw_device_t *device, int fd)
1763{
1764 return 0;
1765}
1766
1767static int adev_close(hw_device_t *device)
1768{
Paul McLeaneedc92e2013-12-19 15:46:15 -08001769 struct audio_device *adev = (struct audio_device *)device;
Simon Wilson19957a32012-04-06 16:17:12 -07001770 free(device);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001771
1772 output_hardware_config_is_cached = false;
Paul McLean30f41852014-04-16 15:44:20 -07001773 input_hardware_config_is_cached = false;
Paul McLeaneedc92e2013-12-19 15:46:15 -08001774
Simon Wilson19957a32012-04-06 16:17:12 -07001775 return 0;
1776}
1777
Paul McLean30f41852014-04-16 15:44:20 -07001778static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device)
Simon Wilson19957a32012-04-06 16:17:12 -07001779{
Simon Wilson19957a32012-04-06 16:17:12 -07001780 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1781 return -EINVAL;
1782
Paul McLeaneedc92e2013-12-19 15:46:15 -08001783 struct audio_device *adev = calloc(1, sizeof(struct audio_device));
Simon Wilson19957a32012-04-06 16:17:12 -07001784 if (!adev)
1785 return -ENOMEM;
1786
1787 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent85e08e22012-08-28 14:30:35 -07001788 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson19957a32012-04-06 16:17:12 -07001789 adev->hw_device.common.module = (struct hw_module_t *) module;
1790 adev->hw_device.common.close = adev_close;
1791
Simon Wilson19957a32012-04-06 16:17:12 -07001792 adev->hw_device.init_check = adev_init_check;
1793 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1794 adev->hw_device.set_master_volume = adev_set_master_volume;
1795 adev->hw_device.set_mode = adev_set_mode;
1796 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1797 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1798 adev->hw_device.set_parameters = adev_set_parameters;
1799 adev->hw_device.get_parameters = adev_get_parameters;
1800 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1801 adev->hw_device.open_output_stream = adev_open_output_stream;
1802 adev->hw_device.close_output_stream = adev_close_output_stream;
1803 adev->hw_device.open_input_stream = adev_open_input_stream;
1804 adev->hw_device.close_input_stream = adev_close_input_stream;
1805 adev->hw_device.dump = adev_dump;
1806
1807 *device = &adev->hw_device.common;
1808
1809 return 0;
1810}
1811
1812static struct hw_module_methods_t hal_module_methods = {
1813 .open = adev_open,
1814};
1815
1816struct audio_module HAL_MODULE_INFO_SYM = {
1817 .common = {
1818 .tag = HARDWARE_MODULE_TAG,
Mike Lockwood46a98092012-04-24 16:41:18 -07001819 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1820 .hal_api_version = HARDWARE_HAL_API_VERSION,
Simon Wilson19957a32012-04-06 16:17:12 -07001821 .id = AUDIO_HARDWARE_MODULE_ID,
1822 .name = "USB audio HW HAL",
1823 .author = "The Android Open Source Project",
1824 .methods = &hal_module_methods,
1825 },
1826};