Author: janderwald
Date: Fri Oct 14 22:08:28 2016
New Revision: 72971
URL:
http://svn.reactos.org/svn/reactos?rev=72971&view=rev
Log:
[USBAUDIO]
- partly implement BuildUSBAudioFilterTopology
Modified:
trunk/reactos/drivers/usb/usbaudio/filter.c
trunk/reactos/drivers/usb/usbaudio/guid.c
trunk/reactos/drivers/usb/usbaudio/usbaudio.h
Modified: trunk/reactos/drivers/usb/usbaudio/filter.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/filte…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/filter.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/filter.c [iso-8859-1] Fri Oct 14 22:08:28 2016
@@ -90,13 +90,270 @@
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)
-{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
+ PKSDEVICE Device,
+ PKSFILTER_DESCRIPTOR FilterDescriptor)
+{
+ 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 @@
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 @@
}
/* build topology */
- Status = BuildUSBAudioFilterTopology(Device);
+ Status = BuildUSBAudioFilterTopology(Device, FilterDescriptor);
if (!NT_SUCCESS(Status))
{
/* failed*/
@@ -570,7 +827,7 @@
/* 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;
}
Modified: trunk/reactos/drivers/usb/usbaudio/guid.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/guid.…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/guid.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/guid.c [iso-8859-1] Fri Oct 14 22:08:28 2016
@@ -7,5 +7,12 @@
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 */
Modified: trunk/reactos/drivers/usb/usbaudio/usbaudio.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/usbau…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/usbaudio.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/usbaudio.h [iso-8859-1] Fri Oct 14 22:08:28 2016
@@ -74,6 +74,34 @@
UCHAR iChannelNames;
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
{