xref: /reactos/drivers/usb/usbaudio/filter.c (revision 845faec4)
1 /*
2 * PROJECT:     ReactOS Universal Audio Class Driver
3 * LICENSE:     GPL - See COPYING in the top level directory
4 * FILE:        drivers/usb/usbaudio/filter.c
5 * PURPOSE:     USB Audio device driver.
6 * PROGRAMMERS:
7 *              Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9 
10 #include "usbaudio.h"
11 
12 GUID NodeTypeMicrophone = { STATIC_KSNODETYPE_MICROPHONE };
13 GUID NodeTypeDesktopMicrophone = { STATIC_KSNODETYPE_DESKTOP_MICROPHONE };
14 GUID NodeTypePersonalMicrophone = { STATIC_KSNODETYPE_PERSONAL_MICROPHONE };
15 GUID NodeTypeOmmniMicrophone = { STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE };
16 GUID NodeTypeArrayMicrophone = { STATIC_KSNODETYPE_MICROPHONE_ARRAY };
17 GUID NodeTypeProcessingArrayMicrophone = { STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY };
18 GUID NodeTypeSpeaker = { STATIC_KSNODETYPE_SPEAKER };
19 GUID NodeTypeHeadphonesSpeaker = { STATIC_KSNODETYPE_HEADPHONES };
20 GUID NodeTypeHMDA = { STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO };
21 GUID NodeTypeDesktopSpeaker = { STATIC_KSNODETYPE_DESKTOP_SPEAKER };
22 GUID NodeTypeRoomSpeaker = { STATIC_KSNODETYPE_ROOM_SPEAKER };
23 GUID NodeTypeCommunicationSpeaker = { STATIC_KSNODETYPE_COMMUNICATION_SPEAKER };
24 GUID NodeTypeSubwoofer = { STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER };
25 GUID NodeTypeCapture = { STATIC_PINNAME_CAPTURE };
26 GUID NodeTypePlayback = { STATIC_KSCATEGORY_AUDIO };
27 GUID GUID_KSCATEGORY_AUDIO = { STATIC_KSCATEGORY_AUDIO };
28 
29 KSPIN_INTERFACE StandardPinInterface =
30 {
31      {STATIC_KSINTERFACESETID_Standard},
32      KSINTERFACE_STANDARD_STREAMING,
33      0
34 };
35 
36 KSPIN_MEDIUM StandardPinMedium =
37 {
38      {STATIC_KSMEDIUMSETID_Standard},
39      KSMEDIUM_TYPE_ANYINSTANCE,
40      0
41 };
42 
43 KSDATARANGE BridgePinAudioFormat[] =
44 {
45     {
46         {
47             sizeof(KSDATAFORMAT),
48             0,
49             0,
50             0,
51             {STATIC_KSDATAFORMAT_TYPE_AUDIO},
52             {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
53             {STATIC_KSDATAFORMAT_SPECIFIER_NONE}
54         }
55     }
56 };
57 
58 static PKSDATARANGE BridgePinAudioFormats[] =
59 {
60     &BridgePinAudioFormat[0]
61 };
62 
63 static LPWSTR ReferenceString = L"global";
64 
65 NTSTATUS
66 NTAPI
67 USBAudioFilterCreate(
68     PKSFILTER Filter,
69     PIRP Irp);
70 
71 static KSFILTER_DISPATCH USBAudioFilterDispatch =
72 {
73     USBAudioFilterCreate,
74     NULL,
75     NULL,
76     NULL
77 };
78 
79 static KSPIN_DISPATCH UsbAudioPinDispatch =
80 {
81     USBAudioPinCreate,
82     USBAudioPinClose,
83     USBAudioPinProcess,
84     USBAudioPinReset,
85     USBAudioPinSetDataFormat,
86     USBAudioPinSetDeviceState,
87     NULL,
88     NULL,
89     NULL,
90     NULL
91 };
92 
93 NTSTATUS NTAPI FilterAudioVolumeHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
94 NTSTATUS NTAPI FilterAudioMuteHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
95 
96 DEFINE_KSPROPERTY_TABLE_AUDIO_VOLUME(FilterAudioVolumePropertySet, FilterAudioVolumeHandler);
97 DEFINE_KSPROPERTY_TABLE_AUDIO_MUTE(FilterAudioMutePropertySet, FilterAudioMuteHandler);
98 
99 
100 static KSPROPERTY_SET FilterAudioVolumePropertySetArray[] =
101 {
102     {
103         &KSPROPSETID_Audio,
104         sizeof(FilterAudioVolumePropertySet) / sizeof(KSPROPERTY_ITEM),
105         (const KSPROPERTY_ITEM*)&FilterAudioVolumePropertySet,
106         0,
107         NULL
108     }
109 };
110 
111 static KSPROPERTY_SET FilterAudioMutePropertySetArray[] =
112 {
113     {
114         &KSPROPSETID_Audio,
115         sizeof(FilterAudioMutePropertySet) / sizeof(KSPROPERTY_ITEM),
116         (const KSPROPERTY_ITEM*)&FilterAudioMutePropertySet,
117         0,
118         NULL
119     }
120 };
121 
122 NTSTATUS
123 UsbAudioGetSetProperty(
124     IN PDEVICE_OBJECT DeviceObject,
125     IN UCHAR Request,
126     IN USHORT Value,
127     IN USHORT Index,
128     IN PVOID TransferBuffer,
129     IN ULONG TransferBufferLength,
130     IN ULONG TransferFlags)
131 {
132     PURB Urb;
133     NTSTATUS Status;
134 
135     /* allocate urb */
136     Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
137     if (!Urb)
138     {
139         /* no memory */
140         return STATUS_INSUFFICIENT_RESOURCES;
141     }
142 
143     /* format urb */
144     UsbBuildVendorRequest(Urb,
145         URB_FUNCTION_CLASS_INTERFACE,
146         sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
147         TransferFlags,
148         0,
149         Request,
150         Value,
151         Index,
152         TransferBuffer,
153         NULL,
154         TransferBufferLength,
155         NULL);
156 
157     /* submit urb */
158     Status = SubmitUrbSync(DeviceObject, Urb);
159 
160     FreeFunction(Urb);
161     return Status;
162 }
163 
164 PNODE_CONTEXT
165 FindNodeContextWithNode(
166     IN PNODE_CONTEXT NodeContext,
167     IN ULONG NodeContextCount,
168     IN ULONG NodeId)
169 {
170     ULONG Index, NodeIndex;
171     for (Index = 0; Index < NodeContextCount; Index++)
172     {
173         for (NodeIndex = 0; NodeIndex < NodeContext[Index].NodeCount; NodeIndex++)
174         {
175             if (NodeContext[Index].Nodes[NodeIndex] == NodeId)
176             {
177                 return &NodeContext[Index];
178             }
179         }
180     }
181     return NULL;
182 }
183 
184 
185 NTSTATUS
186 NTAPI
187 FilterAudioMuteHandler(
188     IN PIRP Irp,
189     IN PKSIDENTIFIER  Request,
190     IN OUT PVOID  Data)
191 {
192     PKSNODEPROPERTY_AUDIO_CHANNEL Property;
193     PKSFILTER Filter;
194     PFILTER_CONTEXT FilterContext;
195     PNODE_CONTEXT NodeContext;
196     PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
197     NTSTATUS Status = STATUS_INVALID_PARAMETER;
198 
199     /* get filter from irp */
200     Filter = KsGetFilterFromIrp(Irp);
201 
202     if (Filter)
203     {
204         /* get property */
205         Property = (PKSNODEPROPERTY_AUDIO_CHANNEL)Request;
206 
207         /* get filter context */
208         FilterContext = (PFILTER_CONTEXT)Filter->Context;
209 
210         /* search for node context */
211         NodeContext = FindNodeContextWithNode(FilterContext->DeviceExtension->NodeContext, FilterContext->DeviceExtension->NodeContextCount, Property->NodeProperty.NodeId);
212         if (NodeContext)
213         {
214             FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)NodeContext->Descriptor;
215             if (Property->NodeProperty.Property.Flags & KSPROPERTY_TYPE_GET)
216             {
217                 Status = UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x81, 0x1 << 8, FeatureUnitDescriptor->bUnitID << 8, Data, 1, USBD_TRANSFER_DIRECTION_IN);
218                 Irp->IoStatus.Information = sizeof(BOOL);
219             }
220             else
221             {
222                 Status = UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x01, 0x1 << 8, FeatureUnitDescriptor->bUnitID << 8, Data, 1, USBD_TRANSFER_DIRECTION_OUT);
223             }
224         }
225     }
226     return Status;
227 }
228 
229 NTSTATUS
230 NTAPI
231 FilterAudioVolumeHandler(
232     IN PIRP Irp,
233     IN PKSIDENTIFIER  Request,
234     IN OUT PVOID  Data)
235 {
236     PKSNODEPROPERTY_AUDIO_CHANNEL Property;
237     PKSFILTER Filter;
238     PFILTER_CONTEXT FilterContext;
239     PNODE_CONTEXT NodeContext;
240     PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
241     PSHORT TransferBuffer;
242     LONG Value;
243     NTSTATUS Status = STATUS_INVALID_PARAMETER;
244 
245 
246     /* get filter from irp */
247     Filter = KsGetFilterFromIrp(Irp);
248 
249     if (Filter)
250     {
251         /* get property */
252         Property = (PKSNODEPROPERTY_AUDIO_CHANNEL)Request;
253 
254         /* get filter context */
255         FilterContext = (PFILTER_CONTEXT)Filter->Context;
256 
257         TransferBuffer = AllocFunction(sizeof(USHORT) * 3);
258         ASSERT(TransferBuffer);
259 
260         Value = *(PLONG)Data;
261 
262         /* search for node context */
263         NodeContext = FindNodeContextWithNode(FilterContext->DeviceExtension->NodeContext, FilterContext->DeviceExtension->NodeContextCount, Property->NodeProperty.NodeId);
264         if (NodeContext)
265         {
266             FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)NodeContext->Descriptor;
267             if (Property->NodeProperty.Property.Flags & KSPROPERTY_TYPE_GET)
268             {
269                 Status = UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x81, 0x2 << 8, FeatureUnitDescriptor->bUnitID << 8, &TransferBuffer[0], sizeof(USHORT), USBD_TRANSFER_DIRECTION_IN);
270                 Value = (LONG)TransferBuffer[0] * 256;
271 
272                 *(PLONG)Data = Value;
273                 Irp->IoStatus.Information = sizeof(BOOL);
274             }
275             else
276             {
277                 /* downscale value */
278                 Value /= 256;
279 
280                 /* get minimum value */
281                 UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x82, 0x2 << 8, FeatureUnitDescriptor->bUnitID << 8, &TransferBuffer[0], sizeof(USHORT), USBD_TRANSFER_DIRECTION_IN);
282 
283                 /* get maximum value */
284                 UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x83, 0x2 << 8, FeatureUnitDescriptor->bUnitID << 8, &TransferBuffer[1], sizeof(USHORT), USBD_TRANSFER_DIRECTION_IN);
285 
286                 if (TransferBuffer[0] > Value)
287                 {
288                     /* use minimum value */
289                     Value = TransferBuffer[0];
290                 }
291 
292                 if (TransferBuffer[1] < Value)
293                 {
294                     /* use maximum value */
295                     Value = TransferBuffer[1];
296                 }
297 
298                 /* store value */
299                 TransferBuffer[2] = Value;
300 
301                 /* set volume request */
302                 Status = UsbAudioGetSetProperty(FilterContext->DeviceExtension->LowerDevice, 0x01, 0x2 << 8, FeatureUnitDescriptor->bUnitID << 8, &TransferBuffer[2], sizeof(USHORT), USBD_TRANSFER_DIRECTION_OUT);
303                 if (NT_SUCCESS(Status))
304                 {
305                     /* store number of bytes transferred*/
306                     Irp->IoStatus.Information = sizeof(LONG);
307                 }
308             }
309         }
310 
311         /* free transfer buffer */
312         FreeFunction(TransferBuffer);
313     }
314     return Status;
315 }
316 
317 
318 ULONG
319 CountTopologyComponents(
320     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
321     OUT PULONG OutDescriptorCount)
322 {
323     PUSB_INTERFACE_DESCRIPTOR Descriptor;
324     PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
325     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
326     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
327     PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
328     PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor;
329     PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR SelectorUnitDescriptor;
330     ULONG NodeCount = 0, Length, Index;
331     ULONG DescriptorCount = 0;
332     UCHAR Value;
333 
334     for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
335     Descriptor != NULL;
336         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
337     {
338         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
339         {
340             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
341             if (InterfaceHeaderDescriptor != NULL)
342             {
343                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
344                 while (CommonDescriptor)
345                 {
346                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
347                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
348                     {
349                         NodeCount++;
350                         DescriptorCount++;
351                     }
352                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
353                     {
354                         FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
355                         DescriptorCount++;
356 
357                         /* get controls from all channels*/
358                         Value = 0;
359                         Length = FeatureUnitDescriptor->bLength - 7;
360                         for (Index = 0; Index < Length; Index++)
361                         {
362                             Value |= FeatureUnitDescriptor->bmaControls[Index];
363                         }
364 
365                         if (Value & 0x01) /* MUTE*/
366                             NodeCount++;
367                         if (Value & 0x02) /* VOLUME */
368                             NodeCount++;
369                         if (Value & 0x04) /* BASS */
370                             NodeCount++;
371                         if (Value & 0x08) /* MID */
372                             NodeCount++;
373                         if (Value & 0x10) /* TREBLE */
374                             NodeCount++;
375                         if (Value & 0x20) /* GRAPHIC EQUALIZER */
376                             NodeCount++;
377                         if (Value & 0x40) /* AUTOMATIC GAIN */
378                             NodeCount++;
379                         if (Value & 0x80) /* DELAY */
380                             NodeCount++;
381                     }
382                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
383                     {
384                         MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
385                         DescriptorCount++;
386                         NodeCount += MixerUnitDescriptor->bNrInPins + 1; /* KSNODETYPE_SUPERMIX for each source pin and KSNODETYPE_SUM for target */
387                     }
388                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x05 /* SELECTOR_UNIT */)
389                     {
390                         SelectorUnitDescriptor = (PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR)InputTerminalDescriptor;
391                         DescriptorCount++;
392                         NodeCount++;
393                     }
394                     else
395                     {
396                         UNIMPLEMENTED;
397                     }
398                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
399                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
400                         break;
401                 }
402             }
403         }
404     }
405     *OutDescriptorCount = DescriptorCount;
406     return NodeCount;
407 }
408 
409 PNODE_CONTEXT
410 FindNodeContextWithId(
411     IN PNODE_CONTEXT NodeContext,
412     IN ULONG NodeContextCount,
413     IN UCHAR TerminalId)
414 {
415     ULONG Index;
416     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor;
417 
418     for (Index = 0; Index < NodeContextCount; Index++)
419     {
420         TerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)NodeContext[Index].Descriptor;
421         if (TerminalDescriptor->bTerminalID == TerminalId)
422             return &NodeContext[Index];
423     }
424     return NULL;
425 }
426 
427 NTSTATUS
428 BuildUSBAudioFilterTopology(
429     PKSDEVICE Device,
430     PKSFILTER_DESCRIPTOR FilterDescriptor)
431 {
432     PDEVICE_EXTENSION DeviceExtension;
433     ULONG NodeCount, Index, DescriptorCount, StreamingTerminalIndex, NonStreamingTerminalDescriptorCount, TotalTerminalDescriptorCount, StreamingTerminalPinOffset, ControlDescriptorCount, Length;
434     UCHAR Value;
435     PUSB_INTERFACE_DESCRIPTOR Descriptor;
436     PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
437     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
438     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
439     PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor;
440     PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor;
441     PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR OutputTerminalDescriptor;
442     PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR SelectorUnitDescriptor;
443     PKSNODE_DESCRIPTOR NodeDescriptors;
444     PNODE_CONTEXT NodeContext, PreviousNodeContext;
445     PKSTOPOLOGY_CONNECTION Connections;
446     PKSAUTOMATION_TABLE AutomationTable;
447 
448     /* get device extension */
449     DeviceExtension = Device->Context;
450 
451     /* count topology nodes */
452     NodeCount = CountTopologyComponents(DeviceExtension->ConfigurationDescriptor, &ControlDescriptorCount);
453 
454     /* init node descriptors*/
455     FilterDescriptor->NodeDescriptors = NodeDescriptors = AllocFunction(NodeCount * sizeof(KSNODE_DESCRIPTOR));
456     if (FilterDescriptor->NodeDescriptors == NULL)
457     {
458         /* no memory */
459         return STATUS_INSUFFICIENT_RESOURCES;
460     }
461     FilterDescriptor->NodeDescriptorSize = sizeof(KSNODE_DESCRIPTOR);
462 
463     DeviceExtension->NodeContext = NodeContext = AllocFunction(sizeof(NODE_CONTEXT) * ControlDescriptorCount);
464     if (!NodeContext)
465     {
466         /* no memory */
467         return STATUS_INSUFFICIENT_RESOURCES;
468     }
469     DeviceExtension->NodeContextCount = ControlDescriptorCount;
470     DescriptorCount = 0;
471 
472     /* first enumerate all topology nodes */
473     for (Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
474     Descriptor != NULL;
475         Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
476     {
477         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
478         {
479             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
480             if (InterfaceHeaderDescriptor != NULL)
481             {
482                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
483                 while (CommonDescriptor)
484                 {
485                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
486                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/)
487                     {
488                         if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
489                         {
490                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
491                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
492                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
493 
494                             /* insert into node context*/
495                             NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
496                             NodeContext[DescriptorCount].NodeCount = 1;
497                             NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
498                             DescriptorCount++;
499 
500                             FilterDescriptor->NodeDescriptorsCount++;
501                         }
502                         else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x200)
503                         {
504                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_ADC;
505                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_ADC;
506                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
507 
508                             /* insert into node context*/
509                             NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
510                             NodeContext[DescriptorCount].NodeCount = 1;
511                             NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
512                             DescriptorCount++;
513 
514 
515                             FilterDescriptor->NodeDescriptorsCount++;
516                         }
517                         else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
518                         {
519                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
520                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
521                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
522 
523                             /* insert into node context*/
524                             NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
525                             NodeContext[DescriptorCount].NodeCount = 1;
526                             NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
527                             DescriptorCount++;
528 
529                             FilterDescriptor->NodeDescriptorsCount++;
530                         }
531                         else
532                         {
533                             DPRINT1("Unexpected input terminal type %x\n", InputTerminalDescriptor->wTerminalType);
534                         }
535                     }
536                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
537                     {
538                         if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
539                         {
540                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
541                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
542                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
543 
544                             /* insert into node context*/
545                             NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
546                             NodeContext[DescriptorCount].NodeCount = 1;
547                             NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
548                             DescriptorCount++;
549 
550                             FilterDescriptor->NodeDescriptorsCount++;
551                         }
552                         else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
553                         {
554                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
555                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
556                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
557 
558                             /* insert into node context*/
559                             NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
560                             NodeContext[DescriptorCount].NodeCount = 1;
561                             NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
562                             DescriptorCount++;
563 
564                             FilterDescriptor->NodeDescriptorsCount++;
565                         }
566                         else
567                         {
568                             DPRINT1("Unexpected output terminal type %x\n", InputTerminalDescriptor->wTerminalType);
569                         }
570                     }
571 
572                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
573                     {
574                         FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)CommonDescriptor;
575 
576                         /* get controls from all channels*/
577                         Value = 0;
578                         Length = FeatureUnitDescriptor->bLength - 7;
579                         for (Index = 0; Index < Length; Index++)
580                         {
581                             Value |= FeatureUnitDescriptor->bmaControls[Index];
582                         }
583 
584 
585                         if (Value & 0x01) /* MUTE*/
586                         {
587                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_MUTE;
588                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_MUTE;
589                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
590                             if (AutomationTable)
591                             {
592                                 AutomationTable->PropertySets = FilterAudioMutePropertySetArray;
593                                 AutomationTable->PropertySetsCount = 1;
594                                 AutomationTable->PropertyItemSize = sizeof(KSPROPERTY_ITEM);
595                             }
596 
597                             /* insert into node context*/
598                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
599                             NodeContext[DescriptorCount].NodeCount++;
600 
601                             FilterDescriptor->NodeDescriptorsCount++;
602                         }
603                         if (Value & 0x02) /* VOLUME */
604                         {
605                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_VOLUME;
606                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_VOLUME;
607                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
608                             if (AutomationTable)
609                             {
610                                 AutomationTable->PropertySets = FilterAudioVolumePropertySetArray;
611                                 AutomationTable->PropertySetsCount = 1;
612                                 AutomationTable->PropertyItemSize = sizeof(KSPROPERTY_ITEM);
613                             }
614 
615                             /* insert into node context*/
616                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
617                             NodeContext[DescriptorCount].NodeCount++;
618 
619                             FilterDescriptor->NodeDescriptorsCount++;
620                         }
621 
622                         if (Value & 0x04) /* BASS */
623                         {
624                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
625                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
626                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
627 
628                             /* insert into node context*/
629                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
630                             NodeContext[DescriptorCount].NodeCount++;
631 
632                             FilterDescriptor->NodeDescriptorsCount++;
633                         }
634 
635                         if (Value & 0x08) /* MID */
636                         {
637                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
638                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
639                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
640 
641                             /* insert into node context*/
642                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
643                             NodeContext[DescriptorCount].NodeCount++;
644 
645                             FilterDescriptor->NodeDescriptorsCount++;
646                         }
647 
648                         if (Value & 0x10) /* TREBLE */
649                         {
650                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
651                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
652                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
653 
654                             /* insert into node context*/
655                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
656                             NodeContext[DescriptorCount].NodeCount++;
657 
658 
659                             FilterDescriptor->NodeDescriptorsCount++;
660                         }
661 
662                         if (Value & 0x20) /* GRAPHIC EQUALIZER */
663                         {
664                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
665                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
666                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
667 
668                             /* insert into node context*/
669                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
670                             NodeContext[DescriptorCount].NodeCount++;
671 
672                             FilterDescriptor->NodeDescriptorsCount++;
673                         }
674 
675                         if (Value & 0x40) /* AUTOMATIC GAIN */
676                         {
677                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_AGC;
678                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_AGC;
679                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
680 
681                             /* insert into node context*/
682                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
683                             NodeContext[DescriptorCount].NodeCount++;
684 
685 
686                             FilterDescriptor->NodeDescriptorsCount++;
687                         }
688 
689                         if (Value & 0x80) /* DELAY */
690                         {
691                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
692                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
693                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
694 
695                             /* insert into node context*/
696                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
697                             NodeContext[DescriptorCount].NodeCount++;
698 
699                             FilterDescriptor->NodeDescriptorsCount++;
700                         }
701                         NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
702                         DescriptorCount++;
703 
704                     }
705                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
706                     {
707                         MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)CommonDescriptor;
708                         for (Index = 0; Index < MixerUnitDescriptor->bNrInPins; Index++)
709                         {
710                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUPERMIX;
711                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUPERMIX;
712                             NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
713 
714                             /* insert into node context*/
715                             NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
716                             NodeContext[DescriptorCount].NodeCount++;
717 
718                             FilterDescriptor->NodeDescriptorsCount++;
719                         }
720 
721                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUM;
722                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUM;
723                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
724 
725                         /* insert into node context*/
726                         NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
727                         NodeContext[DescriptorCount].NodeCount++;
728                         NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
729                         DescriptorCount++;
730 
731                         FilterDescriptor->NodeDescriptorsCount++;
732                     }
733                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x05 /* SELECTOR UNIT */)
734                     {
735                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_MUX;
736                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_MUX;
737                         NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
738 
739                         /* insert into node context*/
740                         NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
741                         NodeContext[DescriptorCount].NodeCount = 1;
742                         NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
743                         DescriptorCount++;
744                         FilterDescriptor->NodeDescriptorsCount++;
745                     }
746                     else
747                     {
748                         UNIMPLEMENTED;
749                     }
750                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
751                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
752                         break;
753                 }
754             }
755         }
756     }
757 
758     /* FIXME determine connections count*/
759     FilterDescriptor->Connections = Connections = AllocFunction(sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->NodeDescriptorsCount * 2);
760     if (!FilterDescriptor->Connections)
761     {
762         /* no memory */
763         return STATUS_INSUFFICIENT_RESOURCES;
764     }
765     FilterDescriptor->ConnectionsCount = 0;
766 
767     /* now build connections array */
768     DescriptorCount = 0;
769     StreamingTerminalIndex = 0;
770     NodeCount = 0;
771 
772     CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
773     StreamingTerminalPinOffset = TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount;
774 
775     for (Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
776     Descriptor != NULL;
777         Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
778     {
779         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
780         {
781             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
782             if (InterfaceHeaderDescriptor != NULL)
783             {
784                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
785                 while (CommonDescriptor)
786                 {
787                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
788                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/)
789                     {
790                         if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
791                         {
792                              Connections[FilterDescriptor->ConnectionsCount].FromNode = KSFILTER_NODE;
793                              Connections[FilterDescriptor->ConnectionsCount].FromNodePin = StreamingTerminalIndex;
794                              Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
795                              Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[0];
796                              FilterDescriptor->ConnectionsCount++;
797                              StreamingTerminalIndex++;
798 
799                         }
800                         else
801                         {
802                             Connections[FilterDescriptor->ConnectionsCount].FromNode = KSFILTER_NODE;
803                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = StreamingTerminalPinOffset;
804                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
805                             Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[0];
806                             FilterDescriptor->ConnectionsCount++;
807                             StreamingTerminalPinOffset++;
808                         }
809                         DescriptorCount++;
810                     }
811                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
812                     {
813                         OutputTerminalDescriptor = (PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
814                         PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, OutputTerminalDescriptor->bSourceID);
815                         if (PreviousNodeContext)
816                         {
817                             Connections[FilterDescriptor->ConnectionsCount].FromNode = PreviousNodeContext->Nodes[PreviousNodeContext->NodeCount - 1];
818                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
819                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
820                             Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[0];
821                             FilterDescriptor->ConnectionsCount++;
822                         }
823 
824                         if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
825                         {
826                             Connections[FilterDescriptor->ConnectionsCount].FromNode = NodeContext[DescriptorCount].Nodes[0];
827                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
828                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = StreamingTerminalIndex;
829                             Connections[FilterDescriptor->ConnectionsCount].ToNode = KSFILTER_NODE;
830                             FilterDescriptor->ConnectionsCount++;
831                             StreamingTerminalIndex++;
832                         }
833                         else
834                         {
835                             Connections[FilterDescriptor->ConnectionsCount].FromNode = NodeContext[DescriptorCount].Nodes[0];
836                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
837                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = StreamingTerminalPinOffset;
838                             Connections[FilterDescriptor->ConnectionsCount].ToNode = KSFILTER_NODE;
839                             FilterDescriptor->ConnectionsCount++;
840 
841                             StreamingTerminalPinOffset++;
842                         }
843                         DescriptorCount++;
844                     }
845                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
846                     {
847                         FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
848                         PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, FeatureUnitDescriptor->bSourceID);
849                         if (PreviousNodeContext)
850                         {
851                             Connections[FilterDescriptor->ConnectionsCount].FromNode = PreviousNodeContext->Nodes[PreviousNodeContext->NodeCount-1];
852                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
853                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
854                             Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[0];
855                             FilterDescriptor->ConnectionsCount++;
856                         }
857                         for (Index = 1; Index < NodeContext[DescriptorCount].NodeCount; Index++)
858                         {
859                             Connections[FilterDescriptor->ConnectionsCount].FromNode = NodeContext[DescriptorCount].Nodes[Index - 1];
860                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
861                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
862                             Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[Index];
863                             FilterDescriptor->ConnectionsCount++;
864                         }
865 
866                         DescriptorCount++;
867                     }
868                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
869                     {
870                         MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
871                         for (Index = 0; Index < MixerUnitDescriptor->bNrInPins; Index++)
872                         {
873                             Value = MixerUnitDescriptor->baSourceID[Index];
874                             PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, Value);
875                             if (PreviousNodeContext)
876                             {
877                                 Connections[FilterDescriptor->ConnectionsCount].FromNode = PreviousNodeContext->Nodes[PreviousNodeContext->NodeCount - 1];
878                                 Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
879                                 Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
880                                 Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[Index];
881                                 FilterDescriptor->ConnectionsCount++;
882                             }
883 
884                             Connections[FilterDescriptor->ConnectionsCount].FromNode = NodeContext[DescriptorCount].Nodes[Index];
885                             Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
886                             Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1 + Index;
887                             Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount-1];
888                             FilterDescriptor->ConnectionsCount++;
889                         }
890                         DescriptorCount++;
891                     }
892                     else if (InputTerminalDescriptor->bDescriptorSubtype == 0x05 /* SELECTOR_UNIT */)
893                     {
894                         SelectorUnitDescriptor = (PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR)InputTerminalDescriptor;
895                         for (Index = 0; Index < SelectorUnitDescriptor->bNrInPins; Index++)
896                         {
897                             Value = SelectorUnitDescriptor->baSourceID[Index];
898                             PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, Value);
899                             if (PreviousNodeContext)
900                             {
901                                 Connections[FilterDescriptor->ConnectionsCount].FromNode = PreviousNodeContext->Nodes[PreviousNodeContext->NodeCount - 1];
902                                 Connections[FilterDescriptor->ConnectionsCount].FromNodePin = 0;
903                                 Connections[FilterDescriptor->ConnectionsCount].ToNodePin = 1;
904                                 Connections[FilterDescriptor->ConnectionsCount].ToNode = NodeContext[DescriptorCount].Nodes[0];
905                                 FilterDescriptor->ConnectionsCount++;
906                             }
907                         }
908                         DescriptorCount++;
909                     }
910                     else
911                     {
912                         UNIMPLEMENTED;
913                     }
914                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
915                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
916                         break;
917                 }
918             }
919         }
920     }
921 
922 
923 
924     return STATUS_SUCCESS;
925 }
926 
927 NTSTATUS
928 NTAPI
929 USBAudioFilterCreate(
930     PKSFILTER Filter,
931     PIRP Irp)
932 {
933     PKSFILTERFACTORY FilterFactory;
934     PKSDEVICE Device;
935     PFILTER_CONTEXT FilterContext;
936 
937     FilterFactory = KsGetParent(Filter);
938     if (FilterFactory == NULL)
939     {
940         /* invalid parameter */
941         return STATUS_INVALID_PARAMETER;
942     }
943 
944     Device = KsGetParent(FilterFactory);
945     if (Device == NULL)
946     {
947         /* invalid parameter */
948         return STATUS_INVALID_PARAMETER;
949     }
950 
951     /* alloc filter context */
952     FilterContext = AllocFunction(sizeof(FILTER_CONTEXT));
953     if (FilterContext == NULL)
954     {
955         /* no memory */
956         return STATUS_INSUFFICIENT_RESOURCES;
957     }
958 
959     /* init context */
960     FilterContext->DeviceExtension = Device->Context;
961     FilterContext->LowerDevice = Device->NextDeviceObject;
962     Filter->Context = FilterContext;
963 
964     DPRINT("USBAudioFilterCreate FilterContext %p LowerDevice %p DeviceExtension %p\n", FilterContext, FilterContext->LowerDevice, FilterContext->DeviceExtension);
965     KsAddItemToObjectBag(Filter->Bag, FilterContext, ExFreePool);
966     return STATUS_SUCCESS;
967 }
968 
969 
970 VOID
971 NTAPI
972 CountTerminalUnits(
973     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
974     OUT PULONG NonStreamingTerminalDescriptorCount,
975     OUT PULONG TotalTerminalDescriptorCount)
976 {
977     PUSB_INTERFACE_DESCRIPTOR Descriptor;
978     PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
979     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
980     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
981     ULONG NonStreamingTerminalCount = 0;
982     ULONG TotalTerminalCount = 0;
983 
984     for(Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
985         Descriptor != NULL;
986         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
987     {
988         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
989         {
990             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
991             if (InterfaceHeaderDescriptor != NULL)
992             {
993                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
994                 while (CommonDescriptor)
995                 {
996                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
997                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
998                     {
999                         if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
1000                         {
1001                             NonStreamingTerminalCount++;
1002                         }
1003                         TotalTerminalCount++;
1004                     }
1005                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
1006                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
1007                         break;
1008                 }
1009             }
1010         }
1011         else if (Descriptor->bInterfaceSubClass == 0x03) /* MIDI_STREAMING */
1012         {
1013             UNIMPLEMENTED;
1014         }
1015     }
1016     *NonStreamingTerminalDescriptorCount = NonStreamingTerminalCount;
1017     *TotalTerminalDescriptorCount = TotalTerminalCount;
1018 }
1019 
1020 LPGUID
1021 UsbAudioGetPinCategoryFromTerminalDescriptor(
1022     IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor)
1023 {
1024     if (TerminalDescriptor->wTerminalType == USB_AUDIO_MICROPHONE_TERMINAL_TYPE)
1025         return &NodeTypeMicrophone;
1026     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE)
1027         return &NodeTypeDesktopMicrophone;
1028     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE)
1029         return &NodeTypePersonalMicrophone;
1030     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE)
1031         return &NodeTypeOmmniMicrophone;
1032     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE)
1033         return &NodeTypeArrayMicrophone;
1034     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE)
1035         return &NodeTypeProcessingArrayMicrophone;
1036 
1037     /* playback types */
1038     if (TerminalDescriptor->wTerminalType == USB_AUDIO_SPEAKER_TERMINAL_TYPE)
1039         return &NodeTypeSpeaker;
1040     else if (TerminalDescriptor->wTerminalType == USB_HEADPHONES_SPEAKER_TERMINAL_TYPE)
1041         return &NodeTypeHeadphonesSpeaker;
1042     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_HMDA_TERMINAL_TYPE)
1043         return &NodeTypeHMDA;
1044     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE)
1045         return &NodeTypeDesktopSpeaker;
1046     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE)
1047         return &NodeTypeRoomSpeaker;
1048     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE)
1049         return &NodeTypeCommunicationSpeaker;
1050     else if (TerminalDescriptor->wTerminalType == USB_AUDIO_SUBWOOFER_TERMINAL_TYPE)
1051         return &NodeTypeSubwoofer;
1052 
1053     if (TerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
1054     {
1055         if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
1056             return &NodeTypeCapture;
1057         else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
1058             return &NodeTypePlayback;
1059 
1060     }
1061     return NULL;
1062 }
1063 
1064 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
1065 UsbAudioGetStreamingTerminalDescriptorByIndex(
1066     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1067     IN ULONG Index)
1068 {
1069     PUSB_INTERFACE_DESCRIPTOR Descriptor;
1070     PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
1071     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
1072     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
1073     ULONG TerminalCount = 0;
1074 
1075     for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
1076     Descriptor != NULL;
1077         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
1078     {
1079         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
1080         {
1081             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1082             if (InterfaceHeaderDescriptor != NULL)
1083             {
1084                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1085                 while (CommonDescriptor)
1086                 {
1087                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
1088                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
1089                     {
1090                         if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
1091                         {
1092                             if (TerminalCount == Index)
1093                             {
1094                                 return InputTerminalDescriptor;
1095                             }
1096                             TerminalCount++;
1097                         }
1098                     }
1099                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
1100                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
1101                         break;
1102                 }
1103             }
1104         }
1105     }
1106     return NULL;
1107 }
1108 
1109 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
1110 UsbAudioGetNonStreamingTerminalDescriptorByIndex(
1111     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1112     IN ULONG Index)
1113 {
1114 
1115     PUSB_INTERFACE_DESCRIPTOR Descriptor;
1116     PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
1117     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
1118     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
1119     ULONG TerminalCount = 0;
1120 
1121     for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
1122     Descriptor != NULL;
1123         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
1124     {
1125         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
1126         {
1127             InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1128             if (InterfaceHeaderDescriptor != NULL)
1129             {
1130                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1131                 while (CommonDescriptor)
1132                 {
1133                     InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
1134                     if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
1135                     {
1136                         if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
1137                         {
1138                             if (TerminalCount == Index)
1139                             {
1140                                 return InputTerminalDescriptor;
1141                             }
1142                             TerminalCount++;
1143                         }
1144                     }
1145                     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
1146                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
1147                         break;
1148                 }
1149             }
1150         }
1151     }
1152     return NULL;
1153 }
1154 
1155 VOID
1156 UsbAudioGetDataRanges(
1157     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
1158     IN UCHAR bTerminalID,
1159     OUT PKSDATARANGE** OutDataRanges,
1160     OUT PULONG OutDataRangesCount)
1161 {
1162     PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor;
1163     PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR StreamingFormatDescriptor;
1164     PUSB_INTERFACE_DESCRIPTOR Descriptor;
1165     PKSDATARANGE_AUDIO DataRangeAudio;
1166     PKSDATARANGE *DataRangeAudioArray;
1167     ULONG NumFrequency, DataRangeCount, DataRangeIndex, Index;
1168 
1169     /* count all data ranges */
1170     DataRangeCount = 0;
1171     for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
1172     Descriptor != NULL;
1173         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
1174     {
1175         if (Descriptor->bInterfaceSubClass == 0x02) /* AUDIO_STREAMING */
1176         {
1177             StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1178             if (StreamingInterfaceDescriptor != NULL)
1179             {
1180                 ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
1181                 ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
1182                 if (StreamingInterfaceDescriptor->bTerminalLink == bTerminalID)
1183                 {
1184                     DataRangeCount++;
1185                     DPRINT1("StreamingInterfaceDescriptor %p TerminalID %x\n", StreamingInterfaceDescriptor, bTerminalID);
1186                 }
1187             }
1188             Descriptor = (PUSB_INTERFACE_DESCRIPTOR)StreamingInterfaceDescriptor;
1189         }
1190     }
1191 
1192     DataRangeAudioArray = AllocFunction(sizeof(PVOID) * DataRangeCount);
1193     if (DataRangeAudioArray == NULL)
1194     {
1195         /* no memory */
1196         return;
1197     }
1198 
1199     DataRangeIndex = 0;
1200     for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
1201     Descriptor != NULL;
1202         Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
1203     {
1204         if (Descriptor->bInterfaceSubClass == 0x02) /* AUDIO_STREAMING */
1205         {
1206             StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
1207             if (StreamingInterfaceDescriptor != NULL)
1208             {
1209                 ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
1210                 ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
1211                 if (StreamingInterfaceDescriptor->bTerminalLink == bTerminalID)
1212                 {
1213                     StreamingFormatDescriptor = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR)((ULONG_PTR)StreamingInterfaceDescriptor + StreamingInterfaceDescriptor->bLength);
1214                     ASSERT(StreamingFormatDescriptor->bDescriptorType == 0x24);
1215                     ASSERT(StreamingFormatDescriptor->bDescriptorSubtype == 0x02);
1216                     ASSERT(StreamingFormatDescriptor->bFormatType == 0x01);
1217 
1218                     DataRangeAudio = AllocFunction(sizeof(KSDATARANGE_AUDIO));
1219                     if (DataRangeAudio == NULL)
1220                     {
1221                         /* no memory*/
1222                         return;
1223                     }
1224 
1225                     DataRangeAudio->DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
1226                     DataRangeAudio->DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
1227                     DataRangeAudio->DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1228                     DataRangeAudio->DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
1229                     DataRangeAudio->MaximumChannels = StreamingFormatDescriptor->bNrChannels;
1230                     DataRangeAudio->MinimumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
1231                     DataRangeAudio->MaximumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
1232                     NumFrequency = StreamingFormatDescriptor->bSamFreqType;
1233                     DataRangeAudio->MinimumSampleFrequency = MAXULONG;
1234                     DataRangeAudio->MaximumSampleFrequency = 0;
1235                     for (Index = 0; Index < NumFrequency; Index++)
1236                     {
1237                         DataRangeAudio->MinimumSampleFrequency = min(StreamingFormatDescriptor->tSamFreq[Index * 3] | StreamingFormatDescriptor->tSamFreq[(Index * 3) + 1] << 8 | StreamingFormatDescriptor->tSamFreq[(Index * 3) + 2] << 16, DataRangeAudio->MinimumSampleFrequency);
1238                         DataRangeAudio->MaximumSampleFrequency = max(StreamingFormatDescriptor->tSamFreq[Index * 3] | StreamingFormatDescriptor->tSamFreq[(Index * 3) + 1] << 8 | StreamingFormatDescriptor->tSamFreq[(Index * 3) + 2] << 16, DataRangeAudio->MaximumSampleFrequency);
1239                     }
1240                     DataRangeAudioArray[DataRangeIndex] = (PKSDATARANGE)DataRangeAudio;
1241                     DataRangeIndex++;
1242                 }
1243             }
1244             Descriptor = (PUSB_INTERFACE_DESCRIPTOR)StreamingInterfaceDescriptor;
1245         }
1246     }
1247 
1248     *OutDataRanges = DataRangeAudioArray;
1249     *OutDataRangesCount = DataRangeCount;
1250 }
1251 
1252 
1253 NTSTATUS
1254 USBAudioPinBuildDescriptors(
1255     PKSDEVICE Device,
1256     PKSPIN_DESCRIPTOR_EX *PinDescriptors,
1257     PULONG PinDescriptorsCount,
1258     PULONG PinDescriptorSize)
1259 {
1260     PDEVICE_EXTENSION DeviceExtension;
1261     PKSPIN_DESCRIPTOR_EX Pins;
1262     ULONG TotalTerminalDescriptorCount = 0;
1263     ULONG NonStreamingTerminalDescriptorCount = 0;
1264     ULONG Index = 0;
1265     PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor = NULL;
1266 
1267     /* get device extension */
1268     DeviceExtension = Device->Context;
1269 
1270     CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
1271     DPRINT("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu\n", TotalTerminalDescriptorCount, NonStreamingTerminalDescriptorCount);
1272 
1273     /* allocate pins */
1274     Pins = AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX) * TotalTerminalDescriptorCount);
1275     if (!Pins)
1276     {
1277         /* no memory*/
1278         return STATUS_INSUFFICIENT_RESOURCES;
1279     }
1280 
1281     for (Index = 0; Index < TotalTerminalDescriptorCount; Index++)
1282     {
1283         if (Index < (TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount))
1284         {
1285             /* irp sink pins*/
1286             TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index);
1287             ASSERT(TerminalDescriptor != NULL);
1288 
1289             Pins[Index].Dispatch = &UsbAudioPinDispatch;
1290             Pins[Index].PinDescriptor.InterfacesCount = 1;
1291             Pins[Index].PinDescriptor.Interfaces = &StandardPinInterface;
1292             Pins[Index].PinDescriptor.MediumsCount = 1;
1293             Pins[Index].PinDescriptor.Mediums = &StandardPinMedium;
1294             Pins[Index].PinDescriptor.Category = UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
1295             UsbAudioGetDataRanges(DeviceExtension->ConfigurationDescriptor, TerminalDescriptor->bTerminalID, (PKSDATARANGE**)&Pins[Index].PinDescriptor.DataRanges, &Pins[Index].PinDescriptor.DataRangesCount);
1296 
1297             if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
1298             {
1299                 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_BOTH;
1300                 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
1301 
1302                 /* pin flags */
1303                 Pins[Index].Flags = KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSFILTER_FLAG_CRITICAL_PROCESSING;
1304             }
1305             else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
1306             {
1307                 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_SINK;
1308                 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
1309 
1310                 /* pin flags */
1311                 Pins[Index].Flags = KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSPIN_FLAG_GENERATE_EOS_EVENTS;
1312             }
1313 
1314             /* data intersect handler */
1315             Pins[Index].IntersectHandler = UsbAudioPinDataIntersect;
1316 
1317             /* irp sinks / sources can be instantiated */
1318             Pins[Index].InstancesPossible = 1;
1319         }
1320         else
1321         {
1322             /* bridge pins */
1323             TerminalDescriptor = UsbAudioGetNonStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index - (TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount));
1324             Pins[Index].PinDescriptor.InterfacesCount = 1;
1325             Pins[Index].PinDescriptor.Interfaces = &StandardPinInterface;
1326             Pins[Index].PinDescriptor.MediumsCount = 1;
1327             Pins[Index].PinDescriptor.Mediums = &StandardPinMedium;
1328             Pins[Index].PinDescriptor.DataRanges = BridgePinAudioFormats;
1329             Pins[Index].PinDescriptor.DataRangesCount = 1;
1330             Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_BRIDGE;
1331             Pins[Index].PinDescriptor.Category = UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
1332 
1333             if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
1334             {
1335                 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
1336             }
1337             else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
1338             {
1339                 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
1340             }
1341         }
1342 
1343     }
1344 
1345     *PinDescriptors = Pins;
1346     *PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR_EX);
1347     *PinDescriptorsCount = TotalTerminalDescriptorCount;
1348 
1349     return STATUS_SUCCESS;
1350 }
1351 
1352 NTSTATUS
1353 NTAPI
1354 USBAudioGetDescriptor(
1355     IN PDEVICE_OBJECT DeviceObject,
1356     IN UCHAR DescriptorType,
1357     IN ULONG DescriptorLength,
1358     IN UCHAR DescriptorIndex,
1359     IN LANGID LanguageId,
1360     OUT PVOID *OutDescriptor)
1361 {
1362     PURB Urb;
1363     NTSTATUS Status;
1364     PVOID Descriptor;
1365 
1366     /* sanity checks */
1367     ASSERT(DeviceObject);
1368     ASSERT(OutDescriptor);
1369     ASSERT(DescriptorLength);
1370 
1371     //
1372     // first allocate descriptor buffer
1373     //
1374     Descriptor = AllocFunction(DescriptorLength);
1375     if (!Descriptor)
1376     {
1377         /* no memory */
1378         return STATUS_INSUFFICIENT_RESOURCES;
1379     }
1380 
1381     /* allocate urb */
1382     Urb = (PURB)AllocFunction(sizeof(URB));
1383     if (!Urb)
1384     {
1385         /* no memory */
1386         FreeFunction(Descriptor);
1387         return STATUS_INSUFFICIENT_RESOURCES;
1388     }
1389 
1390     /* initialize urb */
1391     UsbBuildGetDescriptorRequest(Urb,
1392         sizeof(Urb->UrbControlDescriptorRequest),
1393         DescriptorType,
1394         DescriptorIndex,
1395         LanguageId,
1396         Descriptor,
1397         NULL,
1398         DescriptorLength,
1399         NULL);
1400 
1401     /* submit urb */
1402     Status = SubmitUrbSync(DeviceObject, Urb);
1403 
1404     /* free urb */
1405     FreeFunction(Urb);
1406 
1407     if (NT_SUCCESS(Status))
1408     {
1409         /* store result */
1410         *OutDescriptor = Descriptor;
1411     }
1412     else
1413     {
1414         /* failed */
1415         FreeFunction(Descriptor);
1416     }
1417 
1418     /* done */
1419     return Status;
1420 }
1421 
1422 NTSTATUS
1423 NTAPI
1424 USBAudioGetStringDescriptor(
1425     IN PDEVICE_OBJECT DeviceObject,
1426     IN ULONG DescriptorLength,
1427     IN UCHAR DescriptorIndex,
1428     IN LANGID LanguageId,
1429     OUT PVOID *OutDescriptor)
1430 {
1431     NTSTATUS Status;
1432 
1433     /* retrieve descriptor */
1434     Status = USBAudioGetDescriptor(DeviceObject, USB_STRING_DESCRIPTOR_TYPE, DescriptorLength, DescriptorIndex, LanguageId, OutDescriptor);
1435     if (!NT_SUCCESS(Status))
1436     {
1437         // failed
1438         return Status;
1439     }
1440     return STATUS_SUCCESS;
1441 }
1442 
1443 NTSTATUS
1444 USBAudioRegCreateMediaCategoriesKey(
1445     IN PUNICODE_STRING Name,
1446     OUT PHANDLE OutHandle)
1447 {
1448     NTSTATUS Status;
1449     OBJECT_ATTRIBUTES ObjectAttributes;
1450     UNICODE_STRING DestinationString;
1451     HANDLE Handle;
1452 
1453     /* initialize root name*/
1454     RtlInitUnicodeString(&DestinationString, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
1455 
1456     /* initialize object attributes */
1457     InitializeObjectAttributes(&ObjectAttributes, &DestinationString, OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE, NULL, NULL);
1458 
1459     /* create the key */
1460     Status = ZwOpenKey(&Handle, KEY_ALL_ACCESS, &ObjectAttributes);
1461     if (NT_SUCCESS(Status))
1462     {
1463         /* initialize object attributes */
1464         InitializeObjectAttributes(&ObjectAttributes, Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, Handle, NULL);
1465 
1466         Status = ZwCreateKey(OutHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, 0, NULL);
1467         ZwClose(Handle);
1468 
1469     }
1470     return Status;
1471 }
1472 
1473 
1474 NTSTATUS
1475 USBAudioInitComponentId(
1476     PKSDEVICE Device,
1477     IN PKSCOMPONENTID ComponentId)
1478 {
1479     PDEVICE_EXTENSION DeviceExtension;
1480     NTSTATUS Status;
1481     LPWSTR DescriptionBuffer;
1482     UNICODE_STRING GuidString;
1483     UNICODE_STRING Name;
1484     HANDLE hKey;
1485     GUID TempGuid;
1486 
1487     /* get device extension */
1488     DeviceExtension = Device->Context;
1489 
1490     /* init component id */
1491     ComponentId->Component = KSCOMPONENTID_USBAUDIO;
1492     ComponentId->Version = HIBYTE(DeviceExtension->DeviceDescriptor->bcdDevice);
1493     ComponentId->Revision = LOBYTE(DeviceExtension->DeviceDescriptor->bcdDevice);
1494 
1495     INIT_USBAUDIO_MID(&ComponentId->Manufacturer, DeviceExtension->DeviceDescriptor->idVendor);
1496     INIT_USBAUDIO_PID(&ComponentId->Product, DeviceExtension->DeviceDescriptor->idProduct);
1497     INIT_USBAUDIO_PRODUCT_NAME(&TempGuid, DeviceExtension->DeviceDescriptor->idVendor, DeviceExtension->DeviceDescriptor->idProduct, 0);
1498 
1499     if (DeviceExtension->DeviceDescriptor->iProduct)
1500     {
1501         Status = USBAudioGetStringDescriptor(DeviceExtension->LowerDevice, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iProduct, 0x0409 /* FIXME */, (PVOID*)&DescriptionBuffer);
1502         if (NT_SUCCESS(Status))
1503         {
1504             Status = RtlStringFromGUID(&TempGuid, &GuidString);
1505             if (NT_SUCCESS(Status))
1506             {
1507                 Status = USBAudioRegCreateMediaCategoriesKey(&GuidString, &hKey);
1508                 if (NT_SUCCESS(Status))
1509                 {
1510                     RtlInitUnicodeString(&Name, L"Name");
1511                     ZwSetValueKey(hKey, &Name, 0, REG_SZ, DescriptionBuffer, (wcslen(DescriptionBuffer) + 1) * sizeof(WCHAR));
1512                     ZwClose(hKey);
1513 
1514                     INIT_USBAUDIO_PRODUCT_NAME(&ComponentId->Name, DeviceExtension->DeviceDescriptor->idVendor, DeviceExtension->DeviceDescriptor->idProduct, 0);
1515                 }
1516                 RtlFreeUnicodeString(&GuidString);
1517             }
1518             FreeFunction(DescriptionBuffer);
1519         }
1520     }
1521     return STATUS_SUCCESS;
1522 }
1523 
1524 
1525 NTSTATUS
1526 NTAPI
1527 USBAudioCreateFilterContext(
1528     PKSDEVICE Device)
1529 {
1530     PKSFILTER_DESCRIPTOR FilterDescriptor;
1531     PKSCOMPONENTID ComponentId;
1532     NTSTATUS Status;
1533 
1534     /* allocate descriptor */
1535     FilterDescriptor = AllocFunction(sizeof(KSFILTER_DESCRIPTOR));
1536     if (!FilterDescriptor)
1537     {
1538         /* no memory */
1539         return USBD_STATUS_INSUFFICIENT_RESOURCES;
1540     }
1541 
1542     /* init filter descriptor*/
1543     FilterDescriptor->Version = KSFILTER_DESCRIPTOR_VERSION;
1544     FilterDescriptor->Flags = 0;
1545     FilterDescriptor->ReferenceGuid = &KSNAME_Filter;
1546     FilterDescriptor->Dispatch = &USBAudioFilterDispatch;
1547     FilterDescriptor->CategoriesCount = 1;
1548     FilterDescriptor->Categories = &GUID_KSCATEGORY_AUDIO;
1549 
1550     /* init component id*/
1551     ComponentId = AllocFunction(sizeof(KSCOMPONENTID));
1552     if (!ComponentId)
1553     {
1554         /* no memory */
1555         return STATUS_INSUFFICIENT_RESOURCES;
1556     }
1557     Status = USBAudioInitComponentId(Device, ComponentId);
1558     if (!NT_SUCCESS(Status))
1559     {
1560         /* failed*/
1561         FreeFunction(ComponentId);
1562         return Status;
1563     }
1564     FilterDescriptor->ComponentId = ComponentId;
1565 
1566     /* build pin descriptors */
1567     Status = USBAudioPinBuildDescriptors(Device, (PKSPIN_DESCRIPTOR_EX *)&FilterDescriptor->PinDescriptors, &FilterDescriptor->PinDescriptorsCount, &FilterDescriptor->PinDescriptorSize);
1568     if (!NT_SUCCESS(Status))
1569     {
1570         /* failed*/
1571         FreeFunction(ComponentId);
1572         return Status;
1573     }
1574 
1575     /* build topology */
1576     Status = BuildUSBAudioFilterTopology(Device, FilterDescriptor);
1577     if (!NT_SUCCESS(Status))
1578     {
1579         /* failed*/
1580         FreeFunction(ComponentId);
1581         return Status;
1582     }
1583 
1584     /* lets create the filter */
1585     Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
1586     DPRINT("KsCreateFilterFactory: %x\n", Status);
1587 
1588     return Status;
1589 }
1590 
1591 
1592