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.
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
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
};
29 KSPIN_INTERFACE StandardPinInterface
=
31 {STATIC_KSINTERFACESETID_Standard
},
32 KSINTERFACE_STANDARD_STREAMING
,
36 KSPIN_MEDIUM StandardPinMedium
=
38 {STATIC_KSMEDIUMSETID_Standard
},
39 KSMEDIUM_TYPE_ANYINSTANCE
,
43 KSDATARANGE BridgePinAudioFormat
[] =
51 {STATIC_KSDATAFORMAT_TYPE_AUDIO
},
52 {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG
},
53 {STATIC_KSDATAFORMAT_SPECIFIER_NONE
}
58 static PKSDATARANGE BridgePinAudioFormats
[] =
60 &BridgePinAudioFormat
[0]
63 static LPWSTR ReferenceString
= L
"global";
71 static KSFILTER_DISPATCH USBAudioFilterDispatch
=
79 static KSPIN_DISPATCH UsbAudioPinDispatch
=
85 USBAudioPinSetDataFormat
,
86 USBAudioPinSetDeviceState
,
94 CountTopologyComponents(
95 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
96 OUT PULONG OutDescriptorCount
)
98 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
99 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
100 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
101 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
102 PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor
;
103 PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor
;
105 ULONG DescriptorCount
= 0;
108 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
110 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
112 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
114 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
115 if (InterfaceHeaderDescriptor
!= NULL
)
117 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
118 while (CommonDescriptor
)
120 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
121 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
126 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
128 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
130 Value
= FeatureUnitDescriptor
->bmaControls
[0];
131 if (Value
& 0x01) /* MUTE*/
133 if (Value
& 0x02) /* VOLUME */
135 if (Value
& 0x04) /* BASS */
137 if (Value
& 0x08) /* MID */
139 if (Value
& 0x10) /* TREBLE */
141 if (Value
& 0x20) /* GRAPHIC EQUALIZER */
143 if (Value
& 0x40) /* AUTOMATIC GAIN */
145 if (Value
& 0x80) /* DELAY */
148 /* FIXME handle logical channels too */
150 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
152 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
154 NodeCount
+= MixerUnitDescriptor
->bNrInPins
+ 1; /* KSNODETYPE_SUPERMIX for each source pin and KSNODETYPE_SUM for target */
160 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
161 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
167 *OutDescriptorCount
= DescriptorCount
;
172 FindNodeContextWithId(
173 IN PNODE_CONTEXT NodeContext
,
174 IN ULONG NodeContextCount
,
178 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
;
180 for (Index
= 0; Index
< NodeContextCount
; Index
++)
182 TerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)NodeContext
[Index
].Descriptor
;
183 if (TerminalDescriptor
->bTerminalID
== TerminalId
)
184 return &NodeContext
[Index
];
190 BuildUSBAudioFilterTopology(
192 PKSFILTER_DESCRIPTOR FilterDescriptor
)
194 PDEVICE_EXTENSION DeviceExtension
;
195 ULONG NodeCount
, Index
, DescriptorCount
, StreamingTerminalIndex
, NonStreamingTerminalDescriptorCount
, TotalTerminalDescriptorCount
, StreamingTerminalPinOffset
, ControlDescriptorCount
;
197 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
198 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
199 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
200 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
201 PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor
;
202 PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor
;
203 PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR OutputTerminalDescriptor
;
204 PKSNODE_DESCRIPTOR NodeDescriptors
;
205 PNODE_CONTEXT NodeContext
, PreviousNodeContext
;
206 PKSTOPOLOGY_CONNECTION Connections
;
208 /* get device extension */
209 DeviceExtension
= Device
->Context
;
211 /* count topology nodes */
212 NodeCount
= CountTopologyComponents(DeviceExtension
->ConfigurationDescriptor
, &ControlDescriptorCount
);
214 /* init node descriptors*/
215 FilterDescriptor
->NodeDescriptors
= NodeDescriptors
= AllocFunction(NodeCount
* sizeof(KSNODE_DESCRIPTOR
));
216 if (FilterDescriptor
->NodeDescriptors
== NULL
)
219 return STATUS_INSUFFICIENT_RESOURCES
;
221 FilterDescriptor
->NodeDescriptorSize
= sizeof(KSNODE_DESCRIPTOR
);
223 NodeContext
= AllocFunction(sizeof(NODE_CONTEXT
) * ControlDescriptorCount
);
227 return STATUS_INSUFFICIENT_RESOURCES
;
231 /* first enumerate all topology nodes */
232 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
234 Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
236 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
238 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
239 if (InterfaceHeaderDescriptor
!= NULL
)
241 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
242 while (CommonDescriptor
)
244 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
245 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/)
247 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
249 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SRC
;
250 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SRC
;
251 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
253 /* insert into node context*/
254 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
255 NodeContext
[DescriptorCount
].NodeCount
= 1;
256 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
259 FilterDescriptor
->NodeDescriptorsCount
++;
261 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x200)
263 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_ADC
;
264 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_ADC
;
265 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
267 /* insert into node context*/
268 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
269 NodeContext
[DescriptorCount
].NodeCount
= 1;
270 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
274 FilterDescriptor
->NodeDescriptorsCount
++;
276 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x300)
278 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_DAC
;
279 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_DAC
;
280 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
282 /* insert into node context*/
283 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
284 NodeContext
[DescriptorCount
].NodeCount
= 1;
285 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
288 FilterDescriptor
->NodeDescriptorsCount
++;
292 DPRINT1("Unexpected input terminal type %x\n", InputTerminalDescriptor
->wTerminalType
);
295 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
297 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
299 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SRC
;
300 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SRC
;
301 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
303 /* insert into node context*/
304 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
305 NodeContext
[DescriptorCount
].NodeCount
= 1;
306 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
309 FilterDescriptor
->NodeDescriptorsCount
++;
311 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x300)
313 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_DAC
;
314 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_DAC
;
315 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
317 /* insert into node context*/
318 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
319 NodeContext
[DescriptorCount
].NodeCount
= 1;
320 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
323 FilterDescriptor
->NodeDescriptorsCount
++;
327 DPRINT1("Unexpected output terminal type %x\n", InputTerminalDescriptor
->wTerminalType
);
331 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
333 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)CommonDescriptor
;
334 Value
= FeatureUnitDescriptor
->bmaControls
[0];
335 if (Value
& 0x01) /* MUTE*/
337 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_MUTE
;
338 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_MUTE
;
339 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
341 /* insert into node context*/
342 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
343 NodeContext
[DescriptorCount
].NodeCount
++;
345 FilterDescriptor
->NodeDescriptorsCount
++;
347 if (Value
& 0x02) /* VOLUME */
349 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_VOLUME
;
350 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_VOLUME
;
351 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
353 /* insert into node context*/
354 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
355 NodeContext
[DescriptorCount
].NodeCount
++;
357 FilterDescriptor
->NodeDescriptorsCount
++;
360 if (Value
& 0x04) /* BASS */
362 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
363 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
364 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
366 /* insert into node context*/
367 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
368 NodeContext
[DescriptorCount
].NodeCount
++;
370 FilterDescriptor
->NodeDescriptorsCount
++;
373 if (Value
& 0x08) /* MID */
375 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
376 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
377 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
379 /* insert into node context*/
380 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
381 NodeContext
[DescriptorCount
].NodeCount
++;
383 FilterDescriptor
->NodeDescriptorsCount
++;
386 if (Value
& 0x10) /* TREBLE */
388 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
389 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
390 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
392 /* insert into node context*/
393 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
394 NodeContext
[DescriptorCount
].NodeCount
++;
397 FilterDescriptor
->NodeDescriptorsCount
++;
400 if (Value
& 0x20) /* GRAPHIC EQUALIZER */
402 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
403 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
404 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
406 /* insert into node context*/
407 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
408 NodeContext
[DescriptorCount
].NodeCount
++;
410 FilterDescriptor
->NodeDescriptorsCount
++;
413 if (Value
& 0x40) /* AUTOMATIC GAIN */
415 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
416 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
417 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
419 /* insert into node context*/
420 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
421 NodeContext
[DescriptorCount
].NodeCount
++;
424 FilterDescriptor
->NodeDescriptorsCount
++;
427 if (Value
& 0x80) /* DELAY */
429 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
430 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
431 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
433 /* insert into node context*/
434 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
435 NodeContext
[DescriptorCount
].NodeCount
++;
437 FilterDescriptor
->NodeDescriptorsCount
++;
439 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
443 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
445 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)CommonDescriptor
;
446 for (Index
= 0; Index
< MixerUnitDescriptor
->bNrInPins
; Index
++)
448 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SUPERMIX
;
449 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SUPERMIX
;
450 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
452 /* insert into node context*/
453 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
454 NodeContext
[DescriptorCount
].NodeCount
++;
456 FilterDescriptor
->NodeDescriptorsCount
++;
459 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SUM
;
460 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SUM
;
461 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
463 /* insert into node context*/
464 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
465 NodeContext
[DescriptorCount
].NodeCount
++;
466 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
469 FilterDescriptor
->NodeDescriptorsCount
++;
475 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
476 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
483 /* FIXME determine connections count*/
484 FilterDescriptor
->Connections
= Connections
= AllocFunction(sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->NodeDescriptorsCount
* 2);
485 if (!FilterDescriptor
->Connections
)
488 return STATUS_INSUFFICIENT_RESOURCES
;
490 FilterDescriptor
->ConnectionsCount
= 0;
492 /* now build connections array */
494 StreamingTerminalIndex
= 0;
497 CountTerminalUnits(DeviceExtension
->ConfigurationDescriptor
, &NonStreamingTerminalDescriptorCount
, &TotalTerminalDescriptorCount
);
498 StreamingTerminalPinOffset
= TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
;
500 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
502 Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
504 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
506 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
507 if (InterfaceHeaderDescriptor
!= NULL
)
509 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
510 while (CommonDescriptor
)
512 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
513 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/)
515 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
517 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= KSFILTER_NODE
;
518 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= StreamingTerminalIndex
;
519 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
520 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
521 FilterDescriptor
->ConnectionsCount
++;
522 StreamingTerminalIndex
++;
527 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= KSFILTER_NODE
;
528 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= StreamingTerminalPinOffset
;
529 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
530 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
531 FilterDescriptor
->ConnectionsCount
++;
532 StreamingTerminalPinOffset
++;
536 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
538 OutputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
539 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, OutputTerminalDescriptor
->bSourceID
);
540 if (PreviousNodeContext
)
542 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
- 1];
543 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
544 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
545 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
546 FilterDescriptor
->ConnectionsCount
++;
549 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
551 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[0];
552 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
553 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= StreamingTerminalIndex
;
554 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= KSFILTER_NODE
;
555 FilterDescriptor
->ConnectionsCount
++;
556 StreamingTerminalIndex
++;
560 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[0];
561 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
562 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= StreamingTerminalPinOffset
;
563 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= KSFILTER_NODE
;
564 FilterDescriptor
->ConnectionsCount
++;
566 StreamingTerminalPinOffset
++;
570 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
572 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
573 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, FeatureUnitDescriptor
->bSourceID
);
574 if (PreviousNodeContext
)
576 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
-1];
577 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
578 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
579 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
580 FilterDescriptor
->ConnectionsCount
++;
582 for (Index
= 1; Index
< NodeContext
[DescriptorCount
].NodeCount
; Index
++)
584 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[Index
- 1];
585 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
586 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
587 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
588 FilterDescriptor
->ConnectionsCount
++;
593 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
595 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
596 for (Index
= 0; Index
< MixerUnitDescriptor
->bNrInPins
; Index
++)
598 Value
= MixerUnitDescriptor
->baSourceID
[Index
];
599 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, Value
);
600 if (PreviousNodeContext
)
602 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
- 1];
603 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
604 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
605 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
606 FilterDescriptor
->ConnectionsCount
++;
609 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
610 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
611 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1 + Index
;
612 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
-1];
613 FilterDescriptor
->ConnectionsCount
++;
621 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
622 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
631 return STATUS_SUCCESS
;
636 USBAudioFilterCreate(
640 PKSFILTERFACTORY FilterFactory
;
642 PFILTER_CONTEXT FilterContext
;
644 FilterFactory
= KsGetParent(Filter
);
645 if (FilterFactory
== NULL
)
647 /* invalid parameter */
648 return STATUS_INVALID_PARAMETER
;
651 Device
= KsGetParent(FilterFactory
);
654 /* invalid parameter */
655 return STATUS_INVALID_PARAMETER
;
658 /* alloc filter context */
659 FilterContext
= AllocFunction(sizeof(FILTER_CONTEXT
));
660 if (FilterContext
== NULL
)
663 return STATUS_INSUFFICIENT_RESOURCES
;
667 FilterContext
->DeviceExtension
= Device
->Context
;
668 FilterContext
->LowerDevice
= Device
->NextDeviceObject
;
669 Filter
->Context
= FilterContext
;
671 DPRINT("USBAudioFilterCreate FilterContext %p LowerDevice %p DeviceExtension %p\n", FilterContext
, FilterContext
->LowerDevice
, FilterContext
->DeviceExtension
);
672 KsAddItemToObjectBag(Filter
->Bag
, FilterContext
, ExFreePool
);
673 return STATUS_SUCCESS
;
680 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
681 OUT PULONG NonStreamingTerminalDescriptorCount
,
682 OUT PULONG TotalTerminalDescriptorCount
)
684 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
685 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
686 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
687 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
688 ULONG NonStreamingTerminalCount
= 0;
689 ULONG TotalTerminalCount
= 0;
691 for(Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
693 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
695 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
697 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
698 if (InterfaceHeaderDescriptor
!= NULL
)
700 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
701 while (CommonDescriptor
)
703 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
704 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
706 if (InputTerminalDescriptor
->wTerminalType
!= USB_AUDIO_STREAMING_TERMINAL_TYPE
)
708 NonStreamingTerminalCount
++;
710 TotalTerminalCount
++;
712 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
713 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
718 else if (Descriptor
->bInterfaceSubClass
== 0x03) /* MIDI_STREAMING */
723 *NonStreamingTerminalDescriptorCount
= NonStreamingTerminalCount
;
724 *TotalTerminalDescriptorCount
= TotalTerminalCount
;
728 UsbAudioGetPinCategoryFromTerminalDescriptor(
729 IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
)
731 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_MICROPHONE_TERMINAL_TYPE
)
732 return &NodeTypeMicrophone
;
733 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE
)
734 return &NodeTypeDesktopMicrophone
;
735 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE
)
736 return &NodeTypePersonalMicrophone
;
737 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE
)
738 return &NodeTypeOmmniMicrophone
;
739 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE
)
740 return &NodeTypeArrayMicrophone
;
741 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE
)
742 return &NodeTypeProcessingArrayMicrophone
;
745 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_SPEAKER_TERMINAL_TYPE
)
746 return &NodeTypeSpeaker
;
747 else if (TerminalDescriptor
->wTerminalType
== USB_HEADPHONES_SPEAKER_TERMINAL_TYPE
)
748 return &NodeTypeHeadphonesSpeaker
;
749 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_HMDA_TERMINAL_TYPE
)
750 return &NodeTypeHMDA
;
751 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE
)
752 return &NodeTypeDesktopSpeaker
;
753 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE
)
754 return &NodeTypeRoomSpeaker
;
755 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE
)
756 return &NodeTypeCommunicationSpeaker
;
757 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_SUBWOOFER_TERMINAL_TYPE
)
758 return &NodeTypeSubwoofer
;
760 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
762 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
763 return &NodeTypeCapture
;
764 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
765 return &NodeTypePlayback
;
771 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
772 UsbAudioGetStreamingTerminalDescriptorByIndex(
773 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
776 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
777 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
778 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
779 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
780 ULONG TerminalCount
= 0;
782 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
784 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
786 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
788 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
789 if (InterfaceHeaderDescriptor
!= NULL
)
791 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
792 while (CommonDescriptor
)
794 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
795 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
797 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
799 if (TerminalCount
== Index
)
801 return InputTerminalDescriptor
;
806 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
807 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
816 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
817 UsbAudioGetNonStreamingTerminalDescriptorByIndex(
818 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
822 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
823 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
824 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
825 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
826 ULONG TerminalCount
= 0;
828 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
830 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
832 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
834 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
835 if (InterfaceHeaderDescriptor
!= NULL
)
837 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
838 while (CommonDescriptor
)
840 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
841 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
843 if (InputTerminalDescriptor
->wTerminalType
!= USB_AUDIO_STREAMING_TERMINAL_TYPE
)
845 if (TerminalCount
== Index
)
847 return InputTerminalDescriptor
;
852 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
853 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
863 UsbAudioGetDataRanges(
864 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
865 IN UCHAR bTerminalID
,
866 OUT PKSDATARANGE
** OutDataRanges
,
867 OUT PULONG OutDataRangesCount
)
869 PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor
;
870 PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR StreamingFormatDescriptor
;
871 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
872 PKSDATARANGE_AUDIO DataRangeAudio
;
873 PKSDATARANGE
*DataRangeAudioArray
;
876 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
878 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
880 if (Descriptor
->bInterfaceSubClass
== 0x02) /* AUDIO_STREAMING */
882 StreamingInterfaceDescriptor
= (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
883 if (StreamingInterfaceDescriptor
!= NULL
)
885 ASSERT(StreamingInterfaceDescriptor
->bDescriptorSubtype
== 0x01);
886 ASSERT(StreamingInterfaceDescriptor
->wFormatTag
== WAVE_FORMAT_PCM
);
887 if (StreamingInterfaceDescriptor
->bTerminalLink
== bTerminalID
)
889 StreamingFormatDescriptor
= (PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR
)((ULONG_PTR
)StreamingInterfaceDescriptor
+ StreamingInterfaceDescriptor
->bLength
);
890 ASSERT(StreamingFormatDescriptor
->bDescriptorType
== 0x24);
891 ASSERT(StreamingFormatDescriptor
->bDescriptorSubtype
== 0x02);
892 ASSERT(StreamingFormatDescriptor
->bFormatType
== 0x01);
894 DataRangeAudio
= AllocFunction(sizeof(KSDATARANGE_AUDIO
));
895 if (DataRangeAudio
== NULL
)
901 DataRangeAudio
->DataRange
.FormatSize
= sizeof(KSDATARANGE_AUDIO
);
902 DataRangeAudio
->DataRange
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
903 DataRangeAudio
->DataRange
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
904 DataRangeAudio
->DataRange
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
905 DataRangeAudio
->MaximumChannels
= 1;
906 DataRangeAudio
->MinimumBitsPerSample
= StreamingFormatDescriptor
->bBitResolution
;
907 DataRangeAudio
->MaximumBitsPerSample
= StreamingFormatDescriptor
->bBitResolution
;
908 NumFrequency
= StreamingFormatDescriptor
->bSamFreqType
- 1;
909 DataRangeAudio
->MinimumSampleFrequency
= StreamingFormatDescriptor
->tSamFreq
[0] | StreamingFormatDescriptor
->tSamFreq
[1] << 8 | StreamingFormatDescriptor
->tSamFreq
[2] << 16;
910 DataRangeAudio
->MaximumSampleFrequency
= StreamingFormatDescriptor
->tSamFreq
[NumFrequency
*3] | StreamingFormatDescriptor
->tSamFreq
[NumFrequency
* 3+1] << 8 | StreamingFormatDescriptor
->tSamFreq
[NumFrequency
* 3+2]<<16;
911 DataRangeAudioArray
= AllocFunction(sizeof(PKSDATARANGE_AUDIO
));
912 if (DataRangeAudioArray
== NULL
)
915 FreeFunction(DataRangeAudio
);
918 DataRangeAudioArray
[0] = (PKSDATARANGE
)DataRangeAudio
;
919 *OutDataRanges
= DataRangeAudioArray
;
920 *OutDataRangesCount
= 1;
930 USBAudioPinBuildDescriptors(
932 PKSPIN_DESCRIPTOR_EX
*PinDescriptors
,
933 PULONG PinDescriptorsCount
,
934 PULONG PinDescriptorSize
)
936 PDEVICE_EXTENSION DeviceExtension
;
937 PKSPIN_DESCRIPTOR_EX Pins
;
938 ULONG TotalTerminalDescriptorCount
= 0;
939 ULONG NonStreamingTerminalDescriptorCount
= 0;
941 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
= NULL
;
943 /* get device extension */
944 DeviceExtension
= Device
->Context
;
946 CountTerminalUnits(DeviceExtension
->ConfigurationDescriptor
, &NonStreamingTerminalDescriptorCount
, &TotalTerminalDescriptorCount
);
947 DPRINT("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu\n", TotalTerminalDescriptorCount
, NonStreamingTerminalDescriptorCount
);
950 Pins
= AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX
) * TotalTerminalDescriptorCount
);
954 return STATUS_INSUFFICIENT_RESOURCES
;
957 for (Index
= 0; Index
< TotalTerminalDescriptorCount
; Index
++)
959 if (Index
< (TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
))
962 TerminalDescriptor
= UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension
->ConfigurationDescriptor
, Index
);
963 ASSERT(TerminalDescriptor
!= NULL
);
965 Pins
[Index
].Dispatch
= &UsbAudioPinDispatch
;
966 Pins
[Index
].PinDescriptor
.InterfacesCount
= 1;
967 Pins
[Index
].PinDescriptor
.Interfaces
= &StandardPinInterface
;
968 Pins
[Index
].PinDescriptor
.MediumsCount
= 1;
969 Pins
[Index
].PinDescriptor
.Mediums
= &StandardPinMedium
;
970 Pins
[Index
].PinDescriptor
.Category
= UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor
);
971 UsbAudioGetDataRanges(DeviceExtension
->ConfigurationDescriptor
, TerminalDescriptor
->bTerminalID
, (PKSDATARANGE
**)&Pins
[Index
].PinDescriptor
.DataRanges
, &Pins
[Index
].PinDescriptor
.DataRangesCount
);
973 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
975 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_BOTH
;
976 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_OUT
;
978 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
980 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_SINK
;
981 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_IN
;
984 /* data intersect handler */
985 Pins
[Index
].IntersectHandler
= UsbAudioPinDataIntersect
;
988 Pins
[Index
].Flags
= KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
| KSFILTER_FLAG_CRITICAL_PROCESSING
;
990 /* irp sinks / sources can be instantiated */
991 Pins
[Index
].InstancesPossible
= 1;
992 Pins
[Index
].InstancesNecessary
= 1;
997 TerminalDescriptor
= UsbAudioGetNonStreamingTerminalDescriptorByIndex(DeviceExtension
->ConfigurationDescriptor
, Index
- (TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
));
998 Pins
[Index
].PinDescriptor
.InterfacesCount
= 1;
999 Pins
[Index
].PinDescriptor
.Interfaces
= &StandardPinInterface
;
1000 Pins
[Index
].PinDescriptor
.MediumsCount
= 1;
1001 Pins
[Index
].PinDescriptor
.Mediums
= &StandardPinMedium
;
1002 Pins
[Index
].PinDescriptor
.DataRanges
= BridgePinAudioFormats
;
1003 Pins
[Index
].PinDescriptor
.DataRangesCount
= 1;
1004 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_BRIDGE
;
1005 Pins
[Index
].PinDescriptor
.Category
= UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor
);
1007 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
1009 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_IN
;
1011 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
1013 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_OUT
;
1019 *PinDescriptors
= Pins
;
1020 *PinDescriptorSize
= sizeof(KSPIN_DESCRIPTOR_EX
);
1021 *PinDescriptorsCount
= TotalTerminalDescriptorCount
;
1023 return STATUS_SUCCESS
;
1028 USBAudioGetDescriptor(
1029 IN PDEVICE_OBJECT DeviceObject
,
1030 IN UCHAR DescriptorType
,
1031 IN ULONG DescriptorLength
,
1032 IN UCHAR DescriptorIndex
,
1033 IN LANGID LanguageId
,
1034 OUT PVOID
*OutDescriptor
)
1041 ASSERT(DeviceObject
);
1042 ASSERT(OutDescriptor
);
1043 ASSERT(DescriptorLength
);
1046 // first allocate descriptor buffer
1048 Descriptor
= AllocFunction(DescriptorLength
);
1052 return STATUS_INSUFFICIENT_RESOURCES
;
1056 Urb
= (PURB
)AllocFunction(sizeof(URB
));
1060 FreeFunction(Descriptor
);
1061 return STATUS_INSUFFICIENT_RESOURCES
;
1064 /* initialize urb */
1065 UsbBuildGetDescriptorRequest(Urb
,
1066 sizeof(Urb
->UrbControlDescriptorRequest
),
1076 Status
= SubmitUrbSync(DeviceObject
, Urb
);
1081 if (NT_SUCCESS(Status
))
1084 *OutDescriptor
= Descriptor
;
1089 FreeFunction(Descriptor
);
1098 USBAudioGetStringDescriptor(
1099 IN PDEVICE_OBJECT DeviceObject
,
1100 IN ULONG DescriptorLength
,
1101 IN UCHAR DescriptorIndex
,
1102 IN LANGID LanguageId
,
1103 OUT PVOID
*OutDescriptor
)
1107 /* retrieve descriptor */
1108 Status
= USBAudioGetDescriptor(DeviceObject
, USB_STRING_DESCRIPTOR_TYPE
, DescriptorLength
, DescriptorIndex
, LanguageId
, OutDescriptor
);
1109 if (!NT_SUCCESS(Status
))
1114 return STATUS_SUCCESS
;
1118 USBAudioRegCreateMediaCategoriesKey(
1119 IN PUNICODE_STRING Name
,
1120 OUT PHANDLE OutHandle
)
1123 OBJECT_ATTRIBUTES ObjectAttributes
;
1124 UNICODE_STRING DestinationString
;
1127 /* initialize root name*/
1128 RtlInitUnicodeString(&DestinationString
, L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
1130 /* initialize object attributes */
1131 InitializeObjectAttributes(&ObjectAttributes
, &DestinationString
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1133 /* create the key */
1134 Status
= ZwOpenKey(&Handle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1135 if (NT_SUCCESS(Status
))
1137 /* initialize object attributes */
1138 InitializeObjectAttributes(&ObjectAttributes
, Name
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, Handle
, NULL
);
1140 Status
= ZwCreateKey(OutHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1149 USBAudioInitComponentId(
1151 IN PKSCOMPONENTID ComponentId
)
1153 PDEVICE_EXTENSION DeviceExtension
;
1155 LPWSTR DescriptionBuffer
;
1156 UNICODE_STRING GuidString
;
1157 UNICODE_STRING Name
;
1161 /* get device extension */
1162 DeviceExtension
= Device
->Context
;
1164 /* init component id */
1165 ComponentId
->Component
= KSCOMPONENTID_USBAUDIO
;
1166 ComponentId
->Version
= HIBYTE(DeviceExtension
->DeviceDescriptor
->bcdDevice
);
1167 ComponentId
->Revision
= LOBYTE(DeviceExtension
->DeviceDescriptor
->bcdDevice
);
1169 INIT_USBAUDIO_MID(&ComponentId
->Manufacturer
, DeviceExtension
->DeviceDescriptor
->idVendor
);
1170 INIT_USBAUDIO_PID(&ComponentId
->Product
, DeviceExtension
->DeviceDescriptor
->idProduct
);
1171 INIT_USBAUDIO_PRODUCT_NAME(&TempGuid
, DeviceExtension
->DeviceDescriptor
->idVendor
, DeviceExtension
->DeviceDescriptor
->idProduct
, 0);
1173 if (DeviceExtension
->DeviceDescriptor
->iProduct
)
1175 Status
= USBAudioGetStringDescriptor(DeviceExtension
->LowerDevice
, 100 * sizeof(WCHAR
), DeviceExtension
->DeviceDescriptor
->iProduct
, 0x0409 /* FIXME */, (PVOID
*)&DescriptionBuffer
);
1176 if (NT_SUCCESS(Status
))
1178 Status
= RtlStringFromGUID(&TempGuid
, &GuidString
);
1179 if (NT_SUCCESS(Status
))
1181 Status
= USBAudioRegCreateMediaCategoriesKey(&GuidString
, &hKey
);
1182 if (NT_SUCCESS(Status
))
1184 RtlInitUnicodeString(&Name
, L
"Name");
1185 ZwSetValueKey(hKey
, &Name
, 0, REG_SZ
, DescriptionBuffer
, (wcslen(DescriptionBuffer
) + 1) * sizeof(WCHAR
));
1188 INIT_USBAUDIO_PRODUCT_NAME(&ComponentId
->Name
, DeviceExtension
->DeviceDescriptor
->idVendor
, DeviceExtension
->DeviceDescriptor
->idProduct
, 0);
1190 RtlFreeUnicodeString(&GuidString
);
1192 FreeFunction(DescriptionBuffer
);
1195 return STATUS_SUCCESS
;
1201 USBAudioCreateFilterContext(
1204 PKSFILTER_DESCRIPTOR FilterDescriptor
;
1205 PKSCOMPONENTID ComponentId
;
1208 /* allocate descriptor */
1209 FilterDescriptor
= AllocFunction(sizeof(KSFILTER_DESCRIPTOR
));
1210 if (!FilterDescriptor
)
1213 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
1216 /* init filter descriptor*/
1217 FilterDescriptor
->Version
= KSFILTER_DESCRIPTOR_VERSION
;
1218 FilterDescriptor
->Flags
= 0;
1219 FilterDescriptor
->ReferenceGuid
= &KSNAME_Filter
;
1220 FilterDescriptor
->Dispatch
= &USBAudioFilterDispatch
;
1221 FilterDescriptor
->CategoriesCount
= 1;
1222 FilterDescriptor
->Categories
= &GUID_KSCATEGORY_AUDIO
;
1224 /* init component id*/
1225 ComponentId
= AllocFunction(sizeof(KSCOMPONENTID
));
1229 return STATUS_INSUFFICIENT_RESOURCES
;
1231 Status
= USBAudioInitComponentId(Device
, ComponentId
);
1232 if (!NT_SUCCESS(Status
))
1235 FreeFunction(ComponentId
);
1238 FilterDescriptor
->ComponentId
= ComponentId
;
1240 /* build pin descriptors */
1241 Status
= USBAudioPinBuildDescriptors(Device
, (PKSPIN_DESCRIPTOR_EX
*)&FilterDescriptor
->PinDescriptors
, &FilterDescriptor
->PinDescriptorsCount
, &FilterDescriptor
->PinDescriptorSize
);
1242 if (!NT_SUCCESS(Status
))
1245 FreeFunction(ComponentId
);
1249 /* build topology */
1250 Status
= BuildUSBAudioFilterTopology(Device
, FilterDescriptor
);
1251 if (!NT_SUCCESS(Status
))
1254 FreeFunction(ComponentId
);
1258 /* lets create the filter */
1259 Status
= KsCreateFilterFactory(Device
->FunctionalDeviceObject
, FilterDescriptor
, ReferenceString
, NULL
, KSCREATE_ITEM_FREEONSTOP
, NULL
, NULL
, NULL
);
1260 DPRINT("KsCreateFilterFactory: %x\n", Status
);