[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
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 ULONG
94 CountTopologyComponents(
95 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
96 OUT PULONG OutDescriptorCount)
97 {
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;
104 ULONG NodeCount = 0;
105 ULONG DescriptorCount = 0;
106 UCHAR Value;
107
108 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
109 Descriptor != NULL;
110 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
111 {
112 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
113 {
114 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
115 if (InterfaceHeaderDescriptor != NULL)
116 {
117 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
118 while (CommonDescriptor)
119 {
120 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
121 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
122 {
123 NodeCount++;
124 DescriptorCount++;
125 }
126 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
127 {
128 FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
129 DescriptorCount++;
130 Value = FeatureUnitDescriptor->bmaControls[0];
131 if (Value & 0x01) /* MUTE*/
132 NodeCount++;
133 if (Value & 0x02) /* VOLUME */
134 NodeCount++;
135 if (Value & 0x04) /* BASS */
136 NodeCount++;
137 if (Value & 0x08) /* MID */
138 NodeCount++;
139 if (Value & 0x10) /* TREBLE */
140 NodeCount++;
141 if (Value & 0x20) /* GRAPHIC EQUALIZER */
142 NodeCount++;
143 if (Value & 0x40) /* AUTOMATIC GAIN */
144 NodeCount++;
145 if (Value & 0x80) /* DELAY */
146 NodeCount++;
147
148 /* FIXME handle logical channels too */
149 }
150 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
151 {
152 MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
153 DescriptorCount++;
154 NodeCount += MixerUnitDescriptor->bNrInPins + 1; /* KSNODETYPE_SUPERMIX for each source pin and KSNODETYPE_SUM for target */
155 }
156 else
157 {
158 UNIMPLEMENTED
159 }
160 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
161 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
162 break;
163 }
164 }
165 }
166 }
167 *OutDescriptorCount = DescriptorCount;
168 return NodeCount;
169 }
170
171 PNODE_CONTEXT
172 FindNodeContextWithId(
173 IN PNODE_CONTEXT NodeContext,
174 IN ULONG NodeContextCount,
175 IN UCHAR TerminalId)
176 {
177 ULONG Index;
178 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor;
179
180 for (Index = 0; Index < NodeContextCount; Index++)
181 {
182 TerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)NodeContext[Index].Descriptor;
183 if (TerminalDescriptor->bTerminalID == TerminalId)
184 return &NodeContext[Index];
185 }
186 return NULL;
187 }
188
189 NTSTATUS
190 BuildUSBAudioFilterTopology(
191 PKSDEVICE Device,
192 PKSFILTER_DESCRIPTOR FilterDescriptor)
193 {
194 PDEVICE_EXTENSION DeviceExtension;
195 ULONG NodeCount, Index, DescriptorCount, StreamingTerminalIndex, NonStreamingTerminalDescriptorCount, TotalTerminalDescriptorCount, StreamingTerminalPinOffset, ControlDescriptorCount;
196 UCHAR Value;
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;
207
208 /* get device extension */
209 DeviceExtension = Device->Context;
210
211 /* count topology nodes */
212 NodeCount = CountTopologyComponents(DeviceExtension->ConfigurationDescriptor, &ControlDescriptorCount);
213
214 /* init node descriptors*/
215 FilterDescriptor->NodeDescriptors = NodeDescriptors = AllocFunction(NodeCount * sizeof(KSNODE_DESCRIPTOR));
216 if (FilterDescriptor->NodeDescriptors == NULL)
217 {
218 /* no memory */
219 return STATUS_INSUFFICIENT_RESOURCES;
220 }
221 FilterDescriptor->NodeDescriptorSize = sizeof(KSNODE_DESCRIPTOR);
222
223 NodeContext = AllocFunction(sizeof(NODE_CONTEXT) * ControlDescriptorCount);
224 if (!NodeContext)
225 {
226 /* no memory */
227 return STATUS_INSUFFICIENT_RESOURCES;
228 }
229 DescriptorCount = 0;
230
231 /* first enumerate all topology nodes */
232 for (Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
233 Descriptor != NULL;
234 Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
235 {
236 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
237 {
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)
240 {
241 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
242 while (CommonDescriptor)
243 {
244 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
245 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/)
246 {
247 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
248 {
249 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
250 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
251 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
252
253 /* insert into node context*/
254 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
255 NodeContext[DescriptorCount].NodeCount = 1;
256 NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
257 DescriptorCount++;
258
259 FilterDescriptor->NodeDescriptorsCount++;
260 }
261 else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x200)
262 {
263 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_ADC;
264 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_ADC;
265 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
266
267 /* insert into node context*/
268 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
269 NodeContext[DescriptorCount].NodeCount = 1;
270 NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
271 DescriptorCount++;
272
273
274 FilterDescriptor->NodeDescriptorsCount++;
275 }
276 else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
277 {
278 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
279 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
280 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
281
282 /* insert into node context*/
283 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
284 NodeContext[DescriptorCount].NodeCount = 1;
285 NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
286 DescriptorCount++;
287
288 FilterDescriptor->NodeDescriptorsCount++;
289 }
290 else
291 {
292 DPRINT1("Unexpected input terminal type %x\n", InputTerminalDescriptor->wTerminalType);
293 }
294 }
295 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
296 {
297 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
298 {
299 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SRC;
300 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SRC;
301 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
302
303 /* insert into node context*/
304 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
305 NodeContext[DescriptorCount].NodeCount = 1;
306 NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
307 DescriptorCount++;
308
309 FilterDescriptor->NodeDescriptorsCount++;
310 }
311 else if ((InputTerminalDescriptor->wTerminalType & 0xFF00) == 0x300)
312 {
313 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_DAC;
314 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_DAC;
315 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
316
317 /* insert into node context*/
318 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
319 NodeContext[DescriptorCount].NodeCount = 1;
320 NodeContext[DescriptorCount].Nodes[0] = FilterDescriptor->NodeDescriptorsCount;
321 DescriptorCount++;
322
323 FilterDescriptor->NodeDescriptorsCount++;
324 }
325 else
326 {
327 DPRINT1("Unexpected output terminal type %x\n", InputTerminalDescriptor->wTerminalType);
328 }
329 }
330
331 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
332 {
333 FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)CommonDescriptor;
334 Value = FeatureUnitDescriptor->bmaControls[0];
335 if (Value & 0x01) /* MUTE*/
336 {
337 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_MUTE;
338 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_MUTE;
339 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
340
341 /* insert into node context*/
342 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
343 NodeContext[DescriptorCount].NodeCount++;
344
345 FilterDescriptor->NodeDescriptorsCount++;
346 }
347 if (Value & 0x02) /* VOLUME */
348 {
349 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_VOLUME;
350 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_VOLUME;
351 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
352
353 /* insert into node context*/
354 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
355 NodeContext[DescriptorCount].NodeCount++;
356
357 FilterDescriptor->NodeDescriptorsCount++;
358 }
359
360 if (Value & 0x04) /* BASS */
361 {
362 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
363 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
364 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
365
366 /* insert into node context*/
367 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
368 NodeContext[DescriptorCount].NodeCount++;
369
370 FilterDescriptor->NodeDescriptorsCount++;
371 }
372
373 if (Value & 0x08) /* MID */
374 {
375 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
376 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
377 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
378
379 /* insert into node context*/
380 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
381 NodeContext[DescriptorCount].NodeCount++;
382
383 FilterDescriptor->NodeDescriptorsCount++;
384 }
385
386 if (Value & 0x10) /* TREBLE */
387 {
388 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
389 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
390 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
391
392 /* insert into node context*/
393 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
394 NodeContext[DescriptorCount].NodeCount++;
395
396
397 FilterDescriptor->NodeDescriptorsCount++;
398 }
399
400 if (Value & 0x20) /* GRAPHIC EQUALIZER */
401 {
402 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
403 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
404 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
405
406 /* insert into node context*/
407 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
408 NodeContext[DescriptorCount].NodeCount++;
409
410 FilterDescriptor->NodeDescriptorsCount++;
411 }
412
413 if (Value & 0x40) /* AUTOMATIC GAIN */
414 {
415 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
416 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
417 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
418
419 /* insert into node context*/
420 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
421 NodeContext[DescriptorCount].NodeCount++;
422
423
424 FilterDescriptor->NodeDescriptorsCount++;
425 }
426
427 if (Value & 0x80) /* DELAY */
428 {
429 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_TONE;
430 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_TONE;
431 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
432
433 /* insert into node context*/
434 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
435 NodeContext[DescriptorCount].NodeCount++;
436
437 FilterDescriptor->NodeDescriptorsCount++;
438 }
439 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
440 DescriptorCount++;
441
442 }
443 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
444 {
445 MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)CommonDescriptor;
446 for (Index = 0; Index < MixerUnitDescriptor->bNrInPins; Index++)
447 {
448 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUPERMIX;
449 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUPERMIX;
450 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
451
452 /* insert into node context*/
453 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
454 NodeContext[DescriptorCount].NodeCount++;
455
456 FilterDescriptor->NodeDescriptorsCount++;
457 }
458
459 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Type = &KSNODETYPE_SUM;
460 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].Name = &KSNODETYPE_SUM;
461 NodeDescriptors[FilterDescriptor->NodeDescriptorsCount].AutomationTable = AllocFunction(sizeof(KSAUTOMATION_TABLE));
462
463 /* insert into node context*/
464 NodeContext[DescriptorCount].Nodes[NodeContext[DescriptorCount].NodeCount] = FilterDescriptor->NodeDescriptorsCount;
465 NodeContext[DescriptorCount].NodeCount++;
466 NodeContext[DescriptorCount].Descriptor = CommonDescriptor;
467 DescriptorCount++;
468
469 FilterDescriptor->NodeDescriptorsCount++;
470 }
471 else
472 {
473 UNIMPLEMENTED
474 }
475 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
476 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
477 break;
478 }
479 }
480 }
481 }
482
483 /* FIXME determine connections count*/
484 FilterDescriptor->Connections = Connections = AllocFunction(sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->NodeDescriptorsCount * 2);
485 if (!FilterDescriptor->Connections)
486 {
487 /* no memory */
488 return STATUS_INSUFFICIENT_RESOURCES;
489 }
490 FilterDescriptor->ConnectionsCount = 0;
491
492 /* now build connections array */
493 DescriptorCount = 0;
494 StreamingTerminalIndex = 0;
495 NodeCount = 0;
496
497 CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
498 StreamingTerminalPinOffset = TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount;
499
500 for (Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
501 Descriptor != NULL;
502 Descriptor = USBD_ParseConfigurationDescriptorEx(DeviceExtension->ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
503 {
504 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
505 {
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)
508 {
509 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
510 while (CommonDescriptor)
511 {
512 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
513 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/)
514 {
515 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
516 {
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++;
523
524 }
525 else
526 {
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++;
533 }
534 DescriptorCount++;
535 }
536 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
537 {
538 OutputTerminalDescriptor = (PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
539 PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, OutputTerminalDescriptor->bSourceID);
540 if (PreviousNodeContext)
541 {
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++;
547 }
548
549 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
550 {
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++;
557 }
558 else
559 {
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++;
565
566 StreamingTerminalPinOffset++;
567 }
568 DescriptorCount++;
569 }
570 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x06 /* FEATURE_UNIT*/)
571 {
572 FeatureUnitDescriptor = (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR)InputTerminalDescriptor;
573 PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, FeatureUnitDescriptor->bSourceID);
574 if (PreviousNodeContext)
575 {
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++;
581 }
582 for (Index = 1; Index < NodeContext[DescriptorCount].NodeCount; Index++)
583 {
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++;
589 }
590
591 DescriptorCount++;
592 }
593 else if (InputTerminalDescriptor->bDescriptorSubtype == 0x04 /* MIXER_UNIT */)
594 {
595 MixerUnitDescriptor = (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR)InputTerminalDescriptor;
596 for (Index = 0; Index < MixerUnitDescriptor->bNrInPins; Index++)
597 {
598 Value = MixerUnitDescriptor->baSourceID[Index];
599 PreviousNodeContext = FindNodeContextWithId(NodeContext, ControlDescriptorCount, Value);
600 if (PreviousNodeContext)
601 {
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++;
607 }
608
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++;
614 }
615 DescriptorCount++;
616 }
617 else
618 {
619 UNIMPLEMENTED
620 }
621 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
622 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
623 break;
624 }
625 }
626 }
627 }
628
629
630
631 return STATUS_SUCCESS;
632 }
633
634 NTSTATUS
635 NTAPI
636 USBAudioFilterCreate(
637 PKSFILTER Filter,
638 PIRP Irp)
639 {
640 PKSFILTERFACTORY FilterFactory;
641 PKSDEVICE Device;
642 PFILTER_CONTEXT FilterContext;
643
644 FilterFactory = KsGetParent(Filter);
645 if (FilterFactory == NULL)
646 {
647 /* invalid parameter */
648 return STATUS_INVALID_PARAMETER;
649 }
650
651 Device = KsGetParent(FilterFactory);
652 if (Device == NULL)
653 {
654 /* invalid parameter */
655 return STATUS_INVALID_PARAMETER;
656 }
657
658 /* alloc filter context */
659 FilterContext = AllocFunction(sizeof(FILTER_CONTEXT));
660 if (FilterContext == NULL)
661 {
662 /* no memory */
663 return STATUS_INSUFFICIENT_RESOURCES;
664 }
665
666 /* init context */
667 FilterContext->DeviceExtension = Device->Context;
668 FilterContext->LowerDevice = Device->NextDeviceObject;
669 Filter->Context = FilterContext;
670
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;
674 }
675
676
677 VOID
678 NTAPI
679 CountTerminalUnits(
680 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
681 OUT PULONG NonStreamingTerminalDescriptorCount,
682 OUT PULONG TotalTerminalDescriptorCount)
683 {
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;
690
691 for(Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
692 Descriptor != NULL;
693 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
694 {
695 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
696 {
697 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
698 if (InterfaceHeaderDescriptor != NULL)
699 {
700 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
701 while (CommonDescriptor)
702 {
703 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
704 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
705 {
706 if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
707 {
708 NonStreamingTerminalCount++;
709 }
710 TotalTerminalCount++;
711 }
712 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
713 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
714 break;
715 }
716 }
717 }
718 else if (Descriptor->bInterfaceSubClass == 0x03) /* MIDI_STREAMING */
719 {
720 UNIMPLEMENTED
721 }
722 }
723 *NonStreamingTerminalDescriptorCount = NonStreamingTerminalCount;
724 *TotalTerminalDescriptorCount = TotalTerminalCount;
725 }
726
727 LPGUID
728 UsbAudioGetPinCategoryFromTerminalDescriptor(
729 IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor)
730 {
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;
743
744 /* playback types */
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;
759
760 if (TerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
761 {
762 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
763 return &NodeTypeCapture;
764 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
765 return &NodeTypePlayback;
766
767 }
768 return NULL;
769 }
770
771 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
772 UsbAudioGetStreamingTerminalDescriptorByIndex(
773 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
774 IN ULONG Index)
775 {
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;
781
782 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
783 Descriptor != NULL;
784 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
785 {
786 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
787 {
788 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
789 if (InterfaceHeaderDescriptor != NULL)
790 {
791 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
792 while (CommonDescriptor)
793 {
794 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
795 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
796 {
797 if (InputTerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
798 {
799 if (TerminalCount == Index)
800 {
801 return InputTerminalDescriptor;
802 }
803 TerminalCount++;
804 }
805 }
806 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
807 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
808 break;
809 }
810 }
811 }
812 }
813 return NULL;
814 }
815
816 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
817 UsbAudioGetNonStreamingTerminalDescriptorByIndex(
818 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
819 IN ULONG Index)
820 {
821
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;
827
828 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
829 Descriptor != NULL;
830 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
831 {
832 if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
833 {
834 InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
835 if (InterfaceHeaderDescriptor != NULL)
836 {
837 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
838 while (CommonDescriptor)
839 {
840 InputTerminalDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)CommonDescriptor;
841 if (InputTerminalDescriptor->bDescriptorSubtype == 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor->bDescriptorSubtype == 0x03 /* OUTPUT_TERMINAL*/)
842 {
843 if (InputTerminalDescriptor->wTerminalType != USB_AUDIO_STREAMING_TERMINAL_TYPE)
844 {
845 if (TerminalCount == Index)
846 {
847 return InputTerminalDescriptor;
848 }
849 TerminalCount++;
850 }
851 }
852 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
853 if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
854 break;
855 }
856 }
857 }
858 }
859 return NULL;
860 }
861
862 VOID
863 UsbAudioGetDataRanges(
864 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
865 IN UCHAR bTerminalID,
866 OUT PKSDATARANGE** OutDataRanges,
867 OUT PULONG OutDataRangesCount)
868 {
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;
874 ULONG NumFrequency;
875
876 for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
877 Descriptor != NULL;
878 Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
879 {
880 if (Descriptor->bInterfaceSubClass == 0x02) /* AUDIO_STREAMING */
881 {
882 StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
883 if (StreamingInterfaceDescriptor != NULL)
884 {
885 ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
886 ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
887 if (StreamingInterfaceDescriptor->bTerminalLink == bTerminalID)
888 {
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);
893
894 DataRangeAudio = AllocFunction(sizeof(KSDATARANGE_AUDIO));
895 if (DataRangeAudio == NULL)
896 {
897 /* no memory*/
898 return;
899 }
900
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)
913 {
914 /* no memory */
915 FreeFunction(DataRangeAudio);
916 return;
917 }
918 DataRangeAudioArray[0] = (PKSDATARANGE)DataRangeAudio;
919 *OutDataRanges = DataRangeAudioArray;
920 *OutDataRangesCount = 1;
921 return;
922 }
923 }
924 }
925 }
926 }
927
928
929 NTSTATUS
930 USBAudioPinBuildDescriptors(
931 PKSDEVICE Device,
932 PKSPIN_DESCRIPTOR_EX *PinDescriptors,
933 PULONG PinDescriptorsCount,
934 PULONG PinDescriptorSize)
935 {
936 PDEVICE_EXTENSION DeviceExtension;
937 PKSPIN_DESCRIPTOR_EX Pins;
938 ULONG TotalTerminalDescriptorCount = 0;
939 ULONG NonStreamingTerminalDescriptorCount = 0;
940 ULONG Index = 0;
941 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor = NULL;
942
943 /* get device extension */
944 DeviceExtension = Device->Context;
945
946 CountTerminalUnits(DeviceExtension->ConfigurationDescriptor, &NonStreamingTerminalDescriptorCount, &TotalTerminalDescriptorCount);
947 DPRINT("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu\n", TotalTerminalDescriptorCount, NonStreamingTerminalDescriptorCount);
948
949 /* allocate pins */
950 Pins = AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX) * TotalTerminalDescriptorCount);
951 if (!Pins)
952 {
953 /* no memory*/
954 return STATUS_INSUFFICIENT_RESOURCES;
955 }
956
957 for (Index = 0; Index < TotalTerminalDescriptorCount; Index++)
958 {
959 if (Index < (TotalTerminalDescriptorCount - NonStreamingTerminalDescriptorCount))
960 {
961 /* irp sink pins*/
962 TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index);
963 ASSERT(TerminalDescriptor != NULL);
964
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);
972
973 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
974 {
975 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_BOTH;
976 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
977 }
978 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
979 {
980 Pins[Index].PinDescriptor.Communication = KSPIN_COMMUNICATION_SINK;
981 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
982 }
983
984 /* data intersect handler */
985 Pins[Index].IntersectHandler = UsbAudioPinDataIntersect;
986
987 /* pin flags */
988 Pins[Index].Flags = KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSFILTER_FLAG_CRITICAL_PROCESSING;
989
990 /* irp sinks / sources can be instantiated */
991 Pins[Index].InstancesPossible = 1;
992 Pins[Index].InstancesNecessary = 1;
993 }
994 else
995 {
996 /* bridge pins */
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);
1006
1007 if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
1008 {
1009 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
1010 }
1011 else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
1012 {
1013 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
1014 }
1015 }
1016
1017 }
1018
1019 *PinDescriptors = Pins;
1020 *PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR_EX);
1021 *PinDescriptorsCount = TotalTerminalDescriptorCount;
1022
1023 return STATUS_SUCCESS;
1024 }
1025
1026 NTSTATUS
1027 NTAPI
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)
1035 {
1036 PURB Urb;
1037 NTSTATUS Status;
1038 PVOID Descriptor;
1039
1040 /* sanity checks */
1041 ASSERT(DeviceObject);
1042 ASSERT(OutDescriptor);
1043 ASSERT(DescriptorLength);
1044
1045 //
1046 // first allocate descriptor buffer
1047 //
1048 Descriptor = AllocFunction(DescriptorLength);
1049 if (!Descriptor)
1050 {
1051 /* no memory */
1052 return STATUS_INSUFFICIENT_RESOURCES;
1053 }
1054
1055 /* allocate urb */
1056 Urb = (PURB)AllocFunction(sizeof(URB));
1057 if (!Urb)
1058 {
1059 /* no memory */
1060 FreeFunction(Descriptor);
1061 return STATUS_INSUFFICIENT_RESOURCES;
1062 }
1063
1064 /* initialize urb */
1065 UsbBuildGetDescriptorRequest(Urb,
1066 sizeof(Urb->UrbControlDescriptorRequest),
1067 DescriptorType,
1068 DescriptorIndex,
1069 LanguageId,
1070 Descriptor,
1071 NULL,
1072 DescriptorLength,
1073 NULL);
1074
1075 /* submit urb */
1076 Status = SubmitUrbSync(DeviceObject, Urb);
1077
1078 /* free urb */
1079 FreeFunction(Urb);
1080
1081 if (NT_SUCCESS(Status))
1082 {
1083 /* store result */
1084 *OutDescriptor = Descriptor;
1085 }
1086
1087 /* done */
1088 return Status;
1089 }
1090
1091 NTSTATUS
1092 NTAPI
1093 USBAudioGetStringDescriptor(
1094 IN PDEVICE_OBJECT DeviceObject,
1095 IN ULONG DescriptorLength,
1096 IN UCHAR DescriptorIndex,
1097 IN LANGID LanguageId,
1098 OUT PVOID *OutDescriptor)
1099 {
1100 NTSTATUS Status;
1101 PUSB_STRING_DESCRIPTOR StringDescriptor;
1102
1103 /* retrieve descriptor */
1104 Status = USBAudioGetDescriptor(DeviceObject, USB_STRING_DESCRIPTOR_TYPE, DescriptorLength, DescriptorIndex, LanguageId, OutDescriptor);
1105 if (!NT_SUCCESS(Status))
1106 {
1107 // failed
1108 return Status;
1109 }
1110 return STATUS_SUCCESS;
1111 }
1112
1113 NTSTATUS
1114 USBAudioRegCreateMediaCategoriesKey(
1115 IN PUNICODE_STRING Name,
1116 OUT PHANDLE OutHandle)
1117 {
1118 NTSTATUS Status;
1119 OBJECT_ATTRIBUTES ObjectAttributes;
1120 UNICODE_STRING DestinationString;
1121 HANDLE Handle;
1122
1123 /* initialize root name*/
1124 RtlInitUnicodeString(&DestinationString, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
1125
1126 /* initialize object attributes */
1127 InitializeObjectAttributes(&ObjectAttributes, &DestinationString, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL);
1128
1129 /* create the key */
1130 Status = ZwOpenKey(&Handle, KEY_ALL_ACCESS, &ObjectAttributes);
1131 if (NT_SUCCESS(Status))
1132 {
1133 /* initialize object attributes */
1134 InitializeObjectAttributes(&ObjectAttributes, Name, OBJ_CASE_INSENSITIVE, Handle, NULL);
1135
1136 Status = ZwCreateKey(OutHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, 0, NULL);
1137 ZwClose(Handle);
1138
1139 }
1140 return Status;
1141 }
1142
1143
1144 NTSTATUS
1145 USBAudioInitComponentId(
1146 PKSDEVICE Device,
1147 IN PKSCOMPONENTID ComponentId)
1148 {
1149 PDEVICE_EXTENSION DeviceExtension;
1150 NTSTATUS Status;
1151 LPWSTR DescriptionBuffer;
1152 UNICODE_STRING GuidString;
1153 UNICODE_STRING Name;
1154 HANDLE hKey;
1155 GUID TempGuid;
1156
1157 /* get device extension */
1158 DeviceExtension = Device->Context;
1159
1160 /* init component id */
1161 ComponentId->Component = KSCOMPONENTID_USBAUDIO;
1162 ComponentId->Version = HIBYTE(DeviceExtension->DeviceDescriptor->bcdDevice);
1163 ComponentId->Revision = LOBYTE(DeviceExtension->DeviceDescriptor->bcdDevice);
1164
1165 INIT_USBAUDIO_MID(&ComponentId->Manufacturer, DeviceExtension->DeviceDescriptor->idVendor);
1166 INIT_USBAUDIO_PID(&ComponentId->Product, DeviceExtension->DeviceDescriptor->idProduct);
1167 INIT_USBAUDIO_PRODUCT_NAME(&TempGuid, DeviceExtension->DeviceDescriptor->idVendor, DeviceExtension->DeviceDescriptor->idProduct, 0);
1168
1169 if (DeviceExtension->DeviceDescriptor->iProduct)
1170 {
1171 Status = USBAudioGetStringDescriptor(DeviceExtension->LowerDevice, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iProduct, 0x0409 /* FIXME */, (PVOID*)&DescriptionBuffer);
1172 if (NT_SUCCESS(Status))
1173 {
1174 Status = RtlStringFromGUID(&TempGuid, &GuidString);
1175 if (NT_SUCCESS(Status))
1176 {
1177 Status = USBAudioRegCreateMediaCategoriesKey(&GuidString, &hKey);
1178 if (NT_SUCCESS(Status))
1179 {
1180 RtlInitUnicodeString(&Name, L"Name");
1181 ZwSetValueKey(hKey, &Name, 0, REG_SZ, DescriptionBuffer, (wcslen(DescriptionBuffer) + 1) * sizeof(WCHAR));
1182 ZwClose(hKey);
1183
1184 INIT_USBAUDIO_PRODUCT_NAME(&ComponentId->Name, DeviceExtension->DeviceDescriptor->idVendor, DeviceExtension->DeviceDescriptor->idProduct, 0);
1185 }
1186 RtlFreeUnicodeString(&GuidString);
1187 }
1188 FreeFunction(DescriptionBuffer);
1189 }
1190 }
1191 return STATUS_SUCCESS;
1192 }
1193
1194
1195 NTSTATUS
1196 NTAPI
1197 USBAudioCreateFilterContext(
1198 PKSDEVICE Device)
1199 {
1200 PKSFILTER_DESCRIPTOR FilterDescriptor;
1201 PKSCOMPONENTID ComponentId;
1202 NTSTATUS Status;
1203
1204 /* allocate descriptor */
1205 FilterDescriptor = AllocFunction(sizeof(KSFILTER_DESCRIPTOR));
1206 if (!FilterDescriptor)
1207 {
1208 /* no memory */
1209 return USBD_STATUS_INSUFFICIENT_RESOURCES;
1210 }
1211
1212 /* init filter descriptor*/
1213 FilterDescriptor->Version = KSFILTER_DESCRIPTOR_VERSION;
1214 FilterDescriptor->Flags = 0;
1215 FilterDescriptor->ReferenceGuid = &KSNAME_Filter;
1216 FilterDescriptor->Dispatch = &USBAudioFilterDispatch;
1217 FilterDescriptor->CategoriesCount = 1;
1218 FilterDescriptor->Categories = &GUID_KSCATEGORY_AUDIO;
1219
1220 /* init component id*/
1221 ComponentId = AllocFunction(sizeof(KSCOMPONENTID));
1222 if (!ComponentId)
1223 {
1224 /* no memory */
1225 return STATUS_INSUFFICIENT_RESOURCES;
1226 }
1227 Status = USBAudioInitComponentId(Device, ComponentId);
1228 if (!NT_SUCCESS(Status))
1229 {
1230 /* failed*/
1231 //FreeFunction(ComponentId);
1232 //return Status;
1233 }
1234 FilterDescriptor->ComponentId = ComponentId;
1235
1236 /* build pin descriptors */
1237 Status = USBAudioPinBuildDescriptors(Device, (PKSPIN_DESCRIPTOR_EX *)&FilterDescriptor->PinDescriptors, &FilterDescriptor->PinDescriptorsCount, &FilterDescriptor->PinDescriptorSize);
1238 if (!NT_SUCCESS(Status))
1239 {
1240 /* failed*/
1241 FreeFunction(ComponentId);
1242 return Status;
1243 }
1244
1245 /* build topology */
1246 Status = BuildUSBAudioFilterTopology(Device, FilterDescriptor);
1247 if (!NT_SUCCESS(Status))
1248 {
1249 /* failed*/
1250 //FreeFunction(ComponentId);
1251 //return Status;
1252 }
1253
1254 /* lets create the filter */
1255 Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
1256 DPRINT("KsCreateFilterFactory: %x\n", Status);
1257
1258 return Status;
1259 }
1260
1261