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