[USBAUDIO]

- partly implement BuildUSBAudioFilterTopology

svn path=/trunk/; revision=72971
This commit is contained in:
Johannes Anderwald 2016-10-14 22:08:28 +00:00
parent 1c43c34853
commit 5c2a0471bd
3 changed files with 299 additions and 7 deletions

View file

@ -90,13 +90,270 @@ static KSPIN_DISPATCH UsbAudioPinDispatch =
NULL
};
ULONG
CountTopologyComponents(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
PUSB_INTERFACE_DESCRIPTOR Descriptor;
PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
PUSB_COMMON_DESCRIPTOR CommonDescriptor;
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor;
ULONG NodeCount = 0;
UCHAR Value;
for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
Descriptor != NULL;
Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
{
if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
{
InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
if (InterfaceHeaderDescriptor != NULL)
{
CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
while (CommonDescriptor)
{
InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
{
NodeCount++;
}
else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
{
FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
Value = FeatureUnitDescriptor->bmaControls[0];
if (Value & 0x01) /* MUTE*/
NodeCount++;
if (Value & 0x02) /* VOLUME */
NodeCount++;
if (Value & 0x04) /* BASS */
NodeCount++;
if (Value & 0x08) /* MID */
NodeCount++;
if (Value & 0x10) /* TREBLE */
NodeCount++;
if (Value & 0x20) /* GRAPHIC EQUALIZER */
NodeCount++;
if (Value & 0x40) /* AUTOMATIC GAIN */
NodeCount++;
if (Value & 0x80) /* DELAY */
NodeCount++;
/* FIXME handle logical channels too */
}
else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
{
MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
NodeCount += MixerUnitDescriptor->bNrInPins + 1; /* KSNODETYPE_SUPERMIX for each source pin and KSNODETYPE_SUM for target */
}
else
{
UNIMPLEMENTED
}
CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
break;
}
}
}
}
return NodeCount;
}
NTSTATUS
BuildUSBAudioFilterTopology(
PKSDEVICE Device)
PKSDEVICE Device,
PKSFILTER_DESCRIPTOR FilterDescriptor)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
PDEVICE_EXTENSION DeviceExtension;
ULONG NodeCount, Index;
UCHAR Value;
PUSB_INTERFACE_DESCRIPTOR Descriptor;
PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
PUSB_COMMON_DESCRIPTOR CommonDescriptor;
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor;
PKSNODE_DESCRIPTOR NodeDescriptors;
/* get device extension */
DeviceExtension = Device->Context;
/* count topology nodes */
NodeCount = CountTopologyComponents(DeviceExtension->ConfigurationDescriptor);
/* init node descriptors*/
FilterDescriptor->NodeDescriptors = NodeDescriptors = AllocFunction(NodeCount * sizeof(KSNODE_DESCRIPTOR));
if (FilterDescriptor->NodeDescriptors == NULL)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
FilterDescriptor->NodeDescriptorSize = sizeof(KSNODE_DESCRIPTOR);
for (Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
Descriptor != NULL;
Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
{
if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
{
InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
if (InterfaceHeaderDescriptor != NULL)
{
CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
while (CommonDescriptor)
{
InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
{
if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x200)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_ADC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_ADC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else
{
DPRINT1("Unexpected input terminal type %x\n", InputTerminalDescriptor->wTerminalType);
}
}
else if (InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
{
if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else
{
DPRINT1("Unexpected output terminal type %x\n", InputTerminalDescriptor->wTerminalType);
}
}
else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
{
FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
Value = FeatureUnitDescriptor->bmaControls[0];
if (Value & 0x01) /* MUTE*/
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_MUTE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_MUTE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x02) /* VOLUME */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_VOLUME;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_VOLUME;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x04) /* BASS */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x08) /* MID */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x10) /* TREBLE */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x20) /* GRAPHIC EQUALIZER */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x40) /* AUTOMATIC GAIN */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
if (Value & 0x80) /* DELAY */
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
}
else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
{
MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
for (Index = 0; Index < MixerUnitDescriptor->bNrInPins; Index++)
{
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUPERMIX;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUPERMIX;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUM;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUM;
NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
FilterDescriptor->NodeDescriptorsCount++;
}
else
{
UNIMPLEMENTED
}
CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
break;
}
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS
@ -411,7 +668,7 @@ USBAudioPinBuildDescriptors(
DeviceExtension = Device->Context;
CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
DPRINT1("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu", TotalTerminalDescriptorCount, NonStreamingTerminalDescriptorCount);
DPRINT("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu\n", TotalTerminalDescriptorCount, NonStreamingTerminalDescriptorCount);
/* allocate pins */
Pins = AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX) * TotalTerminalDescriptorCount);
@ -560,7 +817,7 @@ USBAudioCreateFilterContext(
}
/* build topology */
Status = BuildUSBAudioFilterTopology(Device);
Status = BuildUSBAudioFilterTopology(Device, FilterDescriptor);
if (!NT_SUCCESS(Status))
{
/* failed*/
@ -570,7 +827,7 @@ USBAudioCreateFilterContext(
/* lets create the filter */
Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
DPRINT1("KsCreateFilterFactory: %x\n", Status);
DPRINT("KsCreateFilterFactory: %x\n", Status);
return Status;
}

View file

@ -7,5 +7,12 @@ DEFINE_GUID(KSNAME_Filter, 0x9b365890L, 0x165f, 0x11d0, 0xa1, 0x95, 0x00, 0x20,
DEFINE_GUID(KSDATAFORMAT_TYPE_AUDIO, 0x73647561L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
DEFINE_GUID(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, 0x05589f81L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
DEFINE_GUID(KSNODETYPE_SRC, 0x9DB7B9E0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_ADC, 0x4D837FE0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_DAC, 0x507AE360L, 0xC554, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_MUTE, 0x02B223C0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_TONE, 0x7607E580L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_SUM, 0xDA441A60L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_SUPERMIX, 0xE573ADC0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
DEFINE_GUID(KSNODETYPE_VOLUME, 0x3A5ACC00L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */

View file

@ -75,6 +75,34 @@ typedef struct
UCHAR iTerminal;
}USB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR, *PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR;
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bUnitID;
UCHAR bSourceID;
UCHAR bControlSize;
UCHAR bmaControls[1];
UCHAR iFeature;
}USB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR, *PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR;
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bUnitID;
UCHAR bNrInPins;
UCHAR baSourceID[1];
UCHAR bNrChannels;
USHORT wChannelConfig;
UCHAR iChannelNames;
UCHAR bmControls;
UCHAR iMixer;
}USB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR, *PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR;
typedef struct
{
UCHAR bLength;