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