diff options
Diffstat (limited to 'modules/usbaudio')
-rw-r--r-- | modules/usbaudio/alsa_device_profile.c | 31 | ||||
-rw-r--r-- | modules/usbaudio/audio_hw.c | 49 |
2 files changed, 34 insertions, 46 deletions
diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c index c7df00c..5c4edd1 100644 --- a/modules/usbaudio/alsa_device_profile.c +++ b/modules/usbaudio/alsa_device_profile.c @@ -275,28 +275,19 @@ static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min, unsigned max) { - // TODO: Don't return MONO even if the device supports it. This causes problems - // in AudioPolicyManager. Revisit. - static const unsigned std_out_channel_counts[] = {8, 4, 2/*, 1*/}; - static const unsigned std_in_channel_counts[] = {8, 4, 2, 1}; - - unsigned * channel_counts = - profile->direction == PCM_OUT ? std_out_channel_counts : std_in_channel_counts; - unsigned num_channel_counts = - profile->direction == PCM_OUT - ? ARRAY_SIZE(std_out_channel_counts) : ARRAY_SIZE(std_in_channel_counts); + static const unsigned std_channel_counts[] = {8, 4, 2, 1}; unsigned num_counts = 0; unsigned index; /* TODO write a profile_test_channel_count() */ /* Ensure there is at least one invalid channel count to terminate the channel counts array */ - for (index = 0; index < num_channel_counts && + for (index = 0; index < ARRAY_SIZE(std_channel_counts) && num_counts < ARRAY_SIZE(profile->channel_counts) - 1; index++) { /* TODO Do we want a channel counts test? */ - if (channel_counts[index] >= min && channel_counts[index] <= max /* && + if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* && profile_test_channel_count(profile, channel_counts[index])*/) { - profile->channel_counts[num_counts++] = channel_counts[index]; + profile->channel_counts[num_counts++] = std_channel_counts[index]; } } @@ -459,6 +450,7 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile) }; const bool isOutProfile = profile->direction == PCM_OUT; + const char * const * const names_array = isOutProfile ? out_chans_strs : in_chans_strs; const size_t names_size = isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs); @@ -467,12 +459,17 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile) buffer[0] = '\0'; const int buffer_size = ARRAY_SIZE(buffer); int num_entries = 0; - bool stereo_allowed = false; + /* We currently support MONO and STEREO, and always report STEREO but some (many) + * USB Audio Devices may only announce support for MONO (a headset mic for example), or + * The total number of output channels. SO, if the device itself doesn't explicitly + * support STEREO, append to the channel config strings we are generating. + */ + bool stereo_present = false; unsigned index; unsigned channel_count; for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) { - stereo_allowed = stereo_allowed || channel_count == 2; + stereo_present = stereo_present || channel_count == 2; if (channel_count < names_size && names_array[channel_count] != NULL) { if (num_entries++ != 0) { strncat(buffer, "|", buffer_size); @@ -480,14 +477,16 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile) strncat(buffer, names_array[channel_count], buffer_size); } } + /* emulated modes: * always expose stereo as we can emulate it for PCM_OUT */ - if (!stereo_allowed && isOutProfile) { + if (!stereo_present) { if (num_entries++ != 0) { strncat(buffer, "|", buffer_size); } strncat(buffer, names_array[2], buffer_size); /* stereo */ } + return strdup(buffer); } diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c index 664a753..0346408 100644 --- a/modules/usbaudio/audio_hw.c +++ b/modules/usbaudio/audio_hw.c @@ -104,9 +104,11 @@ struct stream_in { alsa_device_profile * profile; alsa_device_proxy proxy; /* state of the stream */ - // not used? - // struct audio_config hal_pcm_config; - + unsigned hal_channel_count; /* channel count exposed to AudioFlinger. + * This may differ from the device channel count when + * the device is not compatible with AudioFlinger + * capabilities, e.g. exposes too many channels or + * too few channels. */ /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */ void * conversion_buffer; /* any conversions are put into here * they could come from here too if @@ -623,25 +625,13 @@ static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) static size_t in_get_buffer_size(const struct audio_stream *stream) { const struct stream_in * in = ((const struct stream_in*)stream); - size_t buffer_size = - proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream)); - ALOGV("in_get_buffer_size() = %zd", buffer_size); - - return buffer_size; + return proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream)); } static uint32_t in_get_channels(const struct audio_stream *stream) { - /* TODO Here is the code we need when we support arbitrary channel counts - * alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy; - * unsigned channel_count = proxy_get_channel_count(proxy); - * uint32_t channel_mask = audio_channel_in_mask_from_count(channel_count); - * ALOGV("in_get_channels() = 0x%X count:%d", channel_mask, channel_count); - * return channel_mask; - */ - /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels - rewrite this to return the ACTUAL channel format */ - return AUDIO_CHANNEL_IN_STEREO; + const struct stream_in *in = (const struct stream_in*)stream; + return audio_channel_in_mask_from_count(in->hal_channel_count); } static audio_format_t in_get_format(const struct audio_stream *stream) @@ -808,7 +798,7 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t byte */ num_read_buff_bytes = bytes; int num_device_channels = proxy_get_channel_count(&in->proxy); - int num_req_channels = 2; /* always, for now */ + int num_req_channels = in->hal_channel_count; if (num_device_channels != num_req_channels) { num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels; @@ -960,19 +950,18 @@ static int adev_open_input_stream(struct audio_hw_device *dev, ret = -EINVAL; } - if (config->channel_mask == AUDIO_CHANNEL_NONE) { - /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input - * formats */ - config->channel_mask = AUDIO_CHANNEL_IN_STEREO; - - } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) { - /* allow only stereo capture for now */ - config->channel_mask = AUDIO_CHANNEL_IN_STEREO; - ret = -EINVAL; + /* Channels */ + unsigned proposed_channel_count = profile_get_default_channel_count(in->profile); + if (k_force_channels) { + proposed_channel_count = k_force_channels; + } else if (config->channel_mask != AUDIO_CHANNEL_NONE) { + proposed_channel_count = audio_channel_count_from_in_mask(config->channel_mask); } - // proxy_config.channels = 0; /* don't change */ - proxy_config.channels = profile_get_default_channel_count(in->profile); + /* we can expose any channel count mask, and emulate internally. */ + config->channel_mask = audio_channel_in_mask_from_count(proposed_channel_count); + in->hal_channel_count = proposed_channel_count; + proxy_config.channels = profile_get_default_channel_count(in->profile); proxy_prepare(&in->proxy, in->profile, &proxy_config); in->standby = true; |