usb_audio: Correct mixup between Input terminals and Input streams.

An "Input" terminal in USB audio terms refers to any stream of audio
going "in" to the USB device, whether that be from the outside world
(e.g. a line in jack) or from the computer (e.g. via USB OUT endpoints.)

So we cannot rely on the terminal type to tell us whether it is an in
or an out for our purposes, we have to check the stream type, and then
use that to declare to multi_audio what kind of stream we have.

Fixes USB audio mixing up inputs and outputs, especially on devices
that only have one or the other and not both. (QEMU manifested
this problem.)
This commit is contained in:
Augustin Cavalier
2021-09-03 11:13:29 -04:00
parent 3f7da9312e
commit 140c408d7b
3 changed files with 14 additions and 15 deletions
@@ -1066,15 +1066,12 @@ AudioControlInterface::InitACHeader(size_t interface,
uint32
AudioControlInterface::GetChannelsDescription(
Vector<multi_channel_info>& Channels, multi_description* Description,
Vector<_AudioControl*>&Terminals)
Vector<multi_channel_info>& Channels, multi_description* Description,
Vector<_AudioControl*>& Terminals, bool isForInput)
{
uint32 addedChannels = 0;
for (int32 i = 0; i < Terminals.Count(); i++) {
bool bIsInputTerminal
= Terminals[i]->SubType() == USB_AUDIO_AC_INPUT_TERMINAL;
AudioChannelCluster* cluster = Terminals[i]->OutCluster();
if (cluster == NULL || cluster->ChannelsCount() <= 0) {
TRACE(ERR, "Terminal #%d ignored due null "
@@ -1083,9 +1080,9 @@ AudioControlInterface::GetChannelsDescription(
}
uint32 channels = GetTerminalChannels(Channels, cluster,
bIsInputTerminal ? B_MULTI_INPUT_CHANNEL : B_MULTI_OUTPUT_CHANNEL);
isForInput ? B_MULTI_INPUT_CHANNEL : B_MULTI_OUTPUT_CHANNEL);
if (bIsInputTerminal)
if (isForInput)
Description->input_channel_count += channels;
else
Description->output_channel_count += channels;
@@ -1134,7 +1131,7 @@ AudioControlInterface::GetTerminalChannels(Vector<multi_channel_info>& Channels,
uint32
AudioControlInterface::GetBusChannelsDescription(
Vector<multi_channel_info>& Channels, multi_description* Description)
Vector<multi_channel_info>& Channels, multi_description* Description)
{
uint32 addedChannels = 0;
@@ -283,7 +283,8 @@ public:
uint32 GetChannelsDescription(
Vector<multi_channel_info>& Channels,
multi_description* Description,
Vector<_AudioControl*>& USBTerminals);
Vector<_AudioControl*>& USBTerminals,
bool isForInput);
uint32 GetBusChannelsDescription(
Vector<multi_channel_info>& Channels,
multi_description* Description);
@@ -493,17 +493,18 @@ Device::_MultiGetDescription(multi_description* multiDescription)
Description.control_panel[0] = '\0';
Vector<_AudioControl*> USBTerminals;
Vector<multi_channel_info> Channels;
// channels (USB I/O terminals) are already in fStreams
// in outputs->inputs order, use them.
// channels (USB I/O terminals) are already in fStreams in outputs->inputs order.
for (int i = 0; i < fStreams.Count(); i++) {
USBTerminals.PushBack(fAudioControl.Find(fStreams[i]->TerminalLink()));
Vector<_AudioControl*> USBTerminal;
USBTerminal.PushBack(fAudioControl.Find(fStreams[i]->TerminalLink()));
fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminal,
fStreams[i]->IsInput());
fStreams[i]->GetFormatsAndRates(&Description);
}
Vector<multi_channel_info> Channels;
fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminals);
fAudioControl.GetBusChannelsDescription(Channels, &Description);
// Description.request_channel_count = channels + bus_channels;