[USBAUDIO]
[reactos.git] / reactos / drivers / usb / usbaudio / filter.c
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 GUID GUID_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO };
29 GUID GUID_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM };
30 GUID GUID_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX };
31 KSPIN_INTERFACE StandardPinInterface =
32 {
33 {STATIC_KSINTERFACESETID_Standard},
34 KSINTERFACE_STANDARD_STREAMING,
35 0
36 };
37
38 KSPIN_MEDIUM StandardPinMedium =
39 {
40 {STATIC_KSMEDIUMSETID_Standard},
41 KSMEDIUM_TYPE_ANYINSTANCE,
42 0
43 };
44
45 KSDATARANGE BridgePinAudioFormat[] =
46 {
47 {
48 {
49 sizeof(KSDATAFORMAT),
50 0,
51 0,
52 0,
53 {STATIC_KSDATAFORMAT_TYPE_AUDIO},
54 {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
55 {STATIC_KSDATAFORMAT_SPECIFIER_NONE}
56 }
57 }
58 };
59
60 static PKSDATARANGE BridgePinAudioFormats[] =
61 {
62 &BridgePinAudioFormat[0]
63 };
64
65 static LPWSTR ReferenceString = L"global";
66
67 NTSTATUS
68 NTAPI
69 USBAudioFilterCreate(
70 PKSFILTER Filter,
71 PIRP Irp);
72
73 static KSFILTER_DISPATCH USBAudioFilterDispatch =
74 {
75 USBAudioFilterCreate,
76 NULL,
77 NULL,
78 NULL
79 };
80
81 static KSPIN_DISPATCH UsbAudioPinDispatch =
82 {
83 USBAudioPinCreate,
84 USBAudioPinClose,
85 USBAudioPinProcess,
86 USBAudioPinReset,
87 USBAudioPinSetDataFormat,
88 USBAudioPinSetDeviceState,
89 NULL,
90 NULL,
91 NULL,
92 NULL
93 };
94
95
96 NTSTATUS
97 BuildUSBAudioFilterTopology(
98 PKSDEVICE Device)
99 {
100 UNIMPLEMENTED
101 return STATUS_NOT_IMPLEMENTED;
102 }
103
104 NTSTATUS
105 NTAPI
106 USBAudioFilterCreate(
107 PKSFILTER Filter,
108 PIRP Irp)
109 {
110 PKSFILTERFACTORY FilterFactory;
111 PKSDEVICE Device;
112 PFILTER_CONTEXT FilterContext;
113
114 FilterFactory = KsGetParent(Filter);
115 if (FilterFactory == NULL)
116 {
117 /* invalid parameter */
118 return STATUS_INVALID_PARAMETER;
119 }
120
121 Device = KsGetParent(FilterFactory);
122 if (Device == NULL)
123 {
124 /* invalid parameter */
125 return STATUS_INVALID_PARAMETER;
126 }
127
128 /* alloc filter context */
129 FilterContext = AllocFunction(sizeof(FILTER_CONTEXT));
130 if (FilterContext == NULL)
131 {
132 /* no memory */
133 return STATUS_INSUFFICIENT_RESOURCES;
134 }
135
136 /* init context */
137 FilterContext->DeviceExtension = Device->Context;
138 FilterContext->LowerDevice = Device->NextDeviceObject;
139 Filter->Context = FilterContext;
140
141 KsAddItemToObjectBag(Filter->Bag, FilterContext, ExFreePool);
142 return STATUS_SUCCESS;
143 }
144
145
146 VOID
147 CountTerminalUnits(
148 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
149 OUT PULONG NonStreamingTerminalDescriptorCount,
150 OUT PULONG TotalTerminalDescriptorCount)
151 {
152 PUSB_INTERFACE_DESCRIPTOR Descriptor;
153 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
154 PUSB_COMMON_DESCRIPTOR CommonDescriptor;
155 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
156 ULONG NonStreamingTerminalCount = 0;
157 ULONG TotalTerminalCount = 0;
158
159 for(Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
160 Descriptor != NULL;
161 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
162 {
163 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
164 {
165 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
166 if (InterfaceHeaderDescriptor != NULL)
167 {
168 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
169 while (CommonDescriptor)
170 {
171 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
172 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
173 {
174 if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
175 {
176 NonStreamingTerminalCount++;
177 }
178 TotalTerminalCount++;
179 }
180 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
181 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
182 break;
183 }
184 }
185 }
186 else if (Descriptor->bInterfaceSubClass == 0x03) /* MIDI_STREAMING */
187 {
188 UNIMPLEMENTED
189 }
190 }
191 *NonStreamingTerminalDescriptorCount = NonStreamingTerminalCount;
192 *TotalTerminalDescriptorCount = TotalTerminalCount;
193 }
194
195 LPGUID
196 UsbAudioGetPinCategoryFromTerminalDescriptor(
197 IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor)
198 {
199 if (TerminalDescriptor->wTerminalType == USB_AUDIO_MICROPHONE_TERMINAL_TYPE)
200 return &NodeTypeMicrophone;
201 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE)
202 return &NodeTypeDesktopMicrophone;
203 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE)
204 return &NodeTypePersonalMicrophone;
205 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE)
206 return &NodeTypeOmmniMicrophone;
207 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE)
208 return &NodeTypeArrayMicrophone;
209 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE)
210 return &NodeTypeProcessingArrayMicrophone;
211
212 /* playback types */
213 if (TerminalDescriptor->wTerminalType == USB_AUDIO_SPEAKER_TERMINAL_TYPE)
214 return &NodeTypeSpeaker;
215 else if (TerminalDescriptor->wTerminalType == USB_HEADPHONES_SPEAKER_TERMINAL_TYPE)
216 return &NodeTypeHeadphonesSpeaker;
217 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_HMDA_TERMINAL_TYPE)
218 return &NodeTypeHMDA;
219 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE)
220 return &NodeTypeDesktopSpeaker;
221 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE)
222 return &NodeTypeRoomSpeaker;
223 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE)
224 return &NodeTypeCommunicationSpeaker;
225 else if (TerminalDescriptor->wTerminalType == USB_AUDIO_SUBWOOFER_TERMINAL_TYPE)
226 return &NodeTypeSubwoofer;
227
228 if (TerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
229 {
230 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
231 return &NodeTypeCapture;
232 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
233 return &NodeTypePlayback;
234
235 }
236 return NULL;
237 }
238
239 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
240 UsbAudioGetStreamingTerminalDescriptorByIndex(
241 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
242 IN ULONG Index)
243 {
244 PUSB_INTERFACE_DESCRIPTOR Descriptor;
245 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
246 PUSB_COMMON_DESCRIPTOR CommonDescriptor;
247 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
248 ULONG TerminalCount = 0;
249
250 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
251 Descriptor != NULL;
252 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
253 {
254 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
255 {
256 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
257 if (InterfaceHeaderDescriptor != NULL)
258 {
259 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
260 while (CommonDescriptor)
261 {
262 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
263 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
264 {
265 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
266 {
267 if (TerminalCount == Index)
268 {
269 return InputTerminalDescriptor;
270 }
271 TerminalCount++;
272 }
273 }
274 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
275 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
276 break;
277 }
278 }
279 }
280 }
281 return NULL;
282 }
283
284 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
285 UsbAudioGetNonStreamingTerminalDescriptorByIndex(
286 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
287 IN ULONG Index)
288 {
289
290 PUSB_INTERFACE_DESCRIPTOR Descriptor;
291 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor;
292 PUSB_COMMON_DESCRIPTOR CommonDescriptor;
293 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor;
294 ULONG TerminalCount = 0;
295
296 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
297 Descriptor != NULL;
298 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
299 {
300 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
301 {
302 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
303 if (InterfaceHeaderDescriptor != NULL)
304 {
305 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
306 while (CommonDescriptor)
307 {
308 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
309 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
310 {
311 if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
312 {
313 if (TerminalCount == Index)
314 {
315 return InputTerminalDescriptor;
316 }
317 TerminalCount++;
318 }
319 }
320 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
321 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
322 break;
323 }
324 }
325 }
326 }
327 return NULL;
328 }
329
330 VOID
331 UsbAudioGetDataRanges(
332 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
333 IN UCHAR bTerminalID,
334 OUT PKSDATARANGE** OutDataRanges,
335 OUT PULONG OutDataRangesCount)
336 {
337 PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor;
338 PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR StreamingFormatDescriptor;
339 PUSB_INTERFACE_DESCRIPTOR Descriptor;
340 PKSDATARANGE_AUDIO DataRangeAudio;
341 PKSDATARANGE *DataRangeAudioArray;
342 ULONG NumFrequency;
343
344 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
345 Descriptor != NULL;
346 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
347 {
348 if (Descriptor->bInterfaceSubClass == 0x02) /* AUDIO_STREAMING */
349 {
350 StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
351 if (StreamingInterfaceDescriptor != NULL)
352 {
353 ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
354 ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
355 if (StreamingInterfaceDescriptor->bTerminalLink == bTerminalID)
356 {
357 StreamingFormatDescriptor = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR)((ULONG_PTR)StreamingInterfaceDescriptor + StreamingInterfaceDescriptor->bLength);
358 ASSERT(StreamingFormatDescriptor->bDescriptorType == 0x24);
359 ASSERT(StreamingFormatDescriptor->bDescriptorSubtype == 0x02);
360 ASSERT(StreamingFormatDescriptor->bFormatType == 0x01);
361
362 DataRangeAudio = AllocFunction(sizeof(KSDATARANGE_AUDIO));
363 if (DataRangeAudio == NULL)
364 {
365 /* no memory*/
366 return;
367 }
368
369 DataRangeAudio->DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
370 DataRangeAudio->DataRange.MajorFormat = GUID_KSDATAFORMAT_TYPE_AUDIO;
371 DataRangeAudio->DataRange.SubFormat = GUID_KSDATAFORMAT_SUBTYPE_PCM;
372 DataRangeAudio->DataRange.Specifier = GUID_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
373 DataRangeAudio->MaximumChannels = 1;
374 DataRangeAudio->MinimumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
375 DataRangeAudio->MaximumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
376 NumFrequency = StreamingFormatDescriptor->bSamFreqType - 1;
377 DataRangeAudio->MinimumSampleFrequency = StreamingFormatDescriptor->tSamFreq[0] | StreamingFormatDescriptor->tSamFreq[1] << 8 | StreamingFormatDescriptor->tSamFreq[2] << 16;
378 DataRangeAudio->MaximumSampleFrequency = StreamingFormatDescriptor->tSamFreq[NumFrequency*3] | StreamingFormatDescriptor->tSamFreq[NumFrequency * 3+1] << 8 | StreamingFormatDescriptor->tSamFreq[NumFrequency * 3+2]<<16;
379 DataRangeAudioArray = AllocFunction(sizeof(PKSDATARANGE_AUDIO));
380 if (DataRangeAudioArray == NULL)
381 {
382 /* no memory */
383 FreeFunction(DataRangeAudio);
384 return;
385 }
386 DataRangeAudioArray[0] = (PKSDATARANGE)DataRangeAudio;
387 *OutDataRanges = DataRangeAudioArray;
388 *OutDataRangesCount = 1;
389 return;
390 }
391 }
392 }
393 }
394 }
395
396
397 NTSTATUS
398 USBAudioPinBuildDescriptors(
399 PKSDEVICE Device,
400 PKSPIN_DESCRIPTOR_EX *PinDescriptors,
401 PULONG PinDescriptorsCount,
402 PULONG PinDescriptorSize)
403 {
404 PDEVICE_EXTENSION DeviceExtension;
405 PKSPIN_DESCRIPTOR_EX Pins;
406 ULONG TotalTerminalDescriptorCount = 0;
407 ULONG NonStreamingTerminalDescriptorCount = 0;
408 ULONG Index = 0;
409 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor = NULL;
410
411 /* get device extension */
412 DeviceExtension = Device->Context;
413
414 CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
415 DPRINT1("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu", TotalTerminalDescriptorCount, NonStreamingTerminalDescriptorCount);
416
417 /* allocate pins */
418 Pins = AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX) * TotalTerminalDescriptorCount);
419 if (!Pins)
420 {
421 /* no memory*/
422 return STATUS_INSUFFICIENT_RESOURCES;
423 }
424
425 for (Index = 0; Index < TotalTerminalDescriptorCount; Index++)
426 {
427 if (Index < (TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount))
428 {
429 /* irp sink pins*/
430 TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index);
431 ASSERT(TerminalDescriptor != NULL);
432
433 Pins[Index].Dispatch = &UsbAudioPinDispatch;
434 Pins[Index].PinDescriptor.InterfacesCount = 1;
435 Pins[Index].PinDescriptor.Interfaces = &StandardPinInterface;
436 Pins[Index].PinDescriptor.MediumsCount = 1;
437 Pins[Index].PinDescriptor.Mediums = &StandardPinMedium;
438 Pins[Index].PinDescriptor.Category = UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
439 UsbAudioGetDataRanges(DeviceExtension->ConfigurationDescriptor, TerminalDescriptor->bTerminalID, (PKSDATARANGE**)&Pins[Index].PinDescriptor.DataRanges, &Pins[Index].PinDescriptor.DataRangesCount);
440
441 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
442 {
443 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_BOTH;
444 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
445 }
446 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
447 {
448 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_SINK;
449 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
450 }
451
452 /* irp sinks / sources can be instantiated */
453 Pins[Index].InstancesPossible = 1;
454 }
455 else
456 {
457 /* bridge pins */
458 TerminalDescriptor = UsbAudioGetNonStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index - (TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount));
459 Pins[Index].PinDescriptor.InterfacesCount = 1;
460 Pins[Index].PinDescriptor.Interfaces = &StandardPinInterface;
461 Pins[Index].PinDescriptor.MediumsCount = 1;
462 Pins[Index].PinDescriptor.Mediums = &StandardPinMedium;
463 Pins[Index].PinDescriptor.DataRanges = BridgePinAudioFormats;
464 Pins[Index].PinDescriptor.DataRangesCount = 1;
465 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_BRIDGE;
466 Pins[Index].PinDescriptor.Category = UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
467
468 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
469 {
470 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
471 }
472 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
473 {
474 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
475 }
476 }
477
478 }
479
480 *PinDescriptors = Pins;
481 *PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR_EX);
482 *PinDescriptorsCount = TotalTerminalDescriptorCount;
483
484 return STATUS_SUCCESS;
485 }
486
487 NTSTATUS
488 USBAudioInitComponentId(
489 PKSDEVICE Device,
490 IN PKSCOMPONENTID ComponentId)
491 {
492 PDEVICE_EXTENSION DeviceExtension;
493
494 /* get device extension */
495 DeviceExtension = Device->Context;
496
497 INIT_USBAUDIO_MID(&ComponentId->Manufacturer, DeviceExtension->DeviceDescriptor->idVendor);
498 INIT_USBAUDIO_PID(&ComponentId->Product, DeviceExtension->DeviceDescriptor->idProduct);
499
500 //ComponentId->Component = KSCOMPONENTID_USBAUDIO;
501 UNIMPLEMENTED
502 return STATUS_NOT_IMPLEMENTED;
503 }
504
505
506 NTSTATUS
507 NTAPI
508 USBAudioCreateFilterContext(
509 PKSDEVICE Device)
510 {
511 PKSFILTER_DESCRIPTOR FilterDescriptor;
512 PKSCOMPONENTID ComponentId;
513 NTSTATUS Status;
514
515 /* allocate descriptor */
516 FilterDescriptor = AllocFunction(sizeof(KSFILTER_DESCRIPTOR));
517 if (!FilterDescriptor)
518 {
519 /* no memory */
520 return USBD_STATUS_INSUFFICIENT_RESOURCES;
521 }
522
523 /* init filter descriptor*/
524 FilterDescriptor->Version = KSFILTER_DESCRIPTOR_VERSION;
525 FilterDescriptor->Flags = 0;
526 FilterDescriptor->ReferenceGuid = &KSNAME_Filter;
527 FilterDescriptor->Dispatch = &USBAudioFilterDispatch;
528 FilterDescriptor->CategoriesCount = 1;
529 FilterDescriptor->Categories = &GUID_KSCATEGORY_AUDIO;
530
531 /* init component id*/
532 ComponentId = AllocFunction(sizeof(KSCOMPONENTID));
533 if (!ComponentId)
534 {
535 /* no memory */
536 return STATUS_INSUFFICIENT_RESOURCES;
537 }
538 Status = USBAudioInitComponentId(Device, ComponentId);
539 if (!NT_SUCCESS(Status))
540 {
541 /* failed*/
542 //FreeFunction(ComponentId);
543 //return Status;
544 }
545 FilterDescriptor->ComponentId = ComponentId;
546
547 /* build pin descriptors */
548 Status = USBAudioPinBuildDescriptors(Device, (PKSPIN_DESCRIPTOR_EX *)&FilterDescriptor->PinDescriptors, &FilterDescriptor->PinDescriptorsCount, &FilterDescriptor->PinDescriptorSize);
549 if (!NT_SUCCESS(Status))
550 {
551 /* failed*/
552 FreeFunction(ComponentId);
553 return Status;
554 }
555
556 /* build topology */
557 Status = BuildUSBAudioFilterTopology(Device);
558 if (!NT_SUCCESS(Status))
559 {
560 /* failed*/
561 //FreeFunction(ComponentId);
562 //return Status;
563 }
564
565 /* lets create the filter */
566 Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
567 DPRINT1("KsCreateFilterFactory: %x\n", Status);
568
569 return Status;
570 }
571
572