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