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