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.
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
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
};
29 KSPIN_INTERFACE StandardPinInterface
=
31 {STATIC_KSINTERFACESETID_Standard
},
32 KSINTERFACE_STANDARD_STREAMING
,
36 KSPIN_MEDIUM StandardPinMedium
=
38 {STATIC_KSMEDIUMSETID_Standard
},
39 KSMEDIUM_TYPE_ANYINSTANCE
,
43 KSDATARANGE BridgePinAudioFormat
[] =
51 {STATIC_KSDATAFORMAT_TYPE_AUDIO
},
52 {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG
},
53 {STATIC_KSDATAFORMAT_SPECIFIER_NONE
}
58 static PKSDATARANGE BridgePinAudioFormats
[] =
60 &BridgePinAudioFormat
[0]
63 static LPWSTR ReferenceString
= L
"global";
71 static KSFILTER_DISPATCH USBAudioFilterDispatch
=
79 static KSPIN_DISPATCH UsbAudioPinDispatch
=
85 USBAudioPinSetDataFormat
,
86 USBAudioPinSetDeviceState
,
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
);
96 DEFINE_KSPROPERTY_TABLE_AUDIO_VOLUME(FilterAudioVolumePropertySet
, FilterAudioVolumeHandler
);
97 DEFINE_KSPROPERTY_TABLE_AUDIO_MUTE(FilterAudioMutePropertySet
, FilterAudioMuteHandler
);
100 static KSPROPERTY_SET FilterAudioVolumePropertySetArray
[] =
104 sizeof(FilterAudioVolumePropertySet
) / sizeof(KSPROPERTY_ITEM
),
105 (const KSPROPERTY_ITEM
*)&FilterAudioVolumePropertySet
,
111 static KSPROPERTY_SET FilterAudioMutePropertySetArray
[] =
115 sizeof(FilterAudioMutePropertySet
) / sizeof(KSPROPERTY_ITEM
),
116 (const KSPROPERTY_ITEM
*)&FilterAudioMutePropertySet
,
123 UsbAudioGetSetProperty(
124 IN PDEVICE_OBJECT DeviceObject
,
128 IN PVOID TransferBuffer
,
129 IN ULONG TransferBufferLength
,
130 IN ULONG TransferFlags
)
136 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
140 return STATUS_INSUFFICIENT_RESOURCES
;
144 UsbBuildVendorRequest(Urb
,
145 URB_FUNCTION_CLASS_INTERFACE
,
146 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
154 TransferBufferLength
,
158 Status
= SubmitUrbSync(DeviceObject
, Urb
);
165 FindNodeContextWithNode(
166 IN PNODE_CONTEXT NodeContext
,
167 IN ULONG NodeContextCount
,
170 ULONG Index
, NodeIndex
;
171 for (Index
= 0; Index
< NodeContextCount
; Index
++)
173 for (NodeIndex
= 0; NodeIndex
< NodeContext
[Index
].NodeCount
; NodeIndex
++)
175 if (NodeContext
[Index
].Nodes
[NodeIndex
] == NodeId
)
177 return &NodeContext
[Index
];
187 FilterAudioMuteHandler(
189 IN PKSIDENTIFIER Request
,
192 PKSNODEPROPERTY_AUDIO_CHANNEL Property
;
194 PFILTER_CONTEXT FilterContext
;
195 PNODE_CONTEXT NodeContext
;
196 PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor
;
197 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
199 /* get filter from irp */
200 Filter
= KsGetFilterFromIrp(Irp
);
205 Property
= (PKSNODEPROPERTY_AUDIO_CHANNEL
)Request
;
207 /* get filter context */
208 FilterContext
= (PFILTER_CONTEXT
)Filter
->Context
;
210 /* search for node context */
211 NodeContext
= FindNodeContextWithNode(FilterContext
->DeviceExtension
->NodeContext
, FilterContext
->DeviceExtension
->NodeContextCount
, Property
->NodeProperty
.NodeId
);
214 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)NodeContext
->Descriptor
;
215 if (Property
->NodeProperty
.Property
.Flags
& KSPROPERTY_TYPE_GET
)
217 Status
= UsbAudioGetSetProperty(FilterContext
->DeviceExtension
->LowerDevice
, 0x81, 0x1 << 8, FeatureUnitDescriptor
->bUnitID
<< 8, Data
, 1, USBD_TRANSFER_DIRECTION_IN
);
218 Irp
->IoStatus
.Information
= sizeof(BOOL
);
222 Status
= UsbAudioGetSetProperty(FilterContext
->DeviceExtension
->LowerDevice
, 0x01, 0x1 << 8, FeatureUnitDescriptor
->bUnitID
<< 8, Data
, 1, USBD_TRANSFER_DIRECTION_OUT
);
231 FilterAudioVolumeHandler(
233 IN PKSIDENTIFIER Request
,
236 PKSNODEPROPERTY_AUDIO_CHANNEL Property
;
238 PFILTER_CONTEXT FilterContext
;
239 PNODE_CONTEXT NodeContext
;
240 PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor
;
241 PSHORT TransferBuffer
;
243 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
246 /* get filter from irp */
247 Filter
= KsGetFilterFromIrp(Irp
);
252 Property
= (PKSNODEPROPERTY_AUDIO_CHANNEL
)Request
;
254 /* get filter context */
255 FilterContext
= (PFILTER_CONTEXT
)Filter
->Context
;
257 TransferBuffer
= AllocFunction(sizeof(USHORT
) * 3);
258 ASSERT(TransferBuffer
);
260 Value
= *(PLONG
)Data
;
262 /* search for node context */
263 NodeContext
= FindNodeContextWithNode(FilterContext
->DeviceExtension
->NodeContext
, FilterContext
->DeviceExtension
->NodeContextCount
, Property
->NodeProperty
.NodeId
);
266 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)NodeContext
->Descriptor
;
267 if (Property
->NodeProperty
.Property
.Flags
& KSPROPERTY_TYPE_GET
)
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;
272 *(PLONG
)Data
= Value
;
273 Irp
->IoStatus
.Information
= sizeof(BOOL
);
277 /* downscale value */
280 /* get minimum value */
281 UsbAudioGetSetProperty(FilterContext
->DeviceExtension
->LowerDevice
, 0x82, 0x2 << 8, FeatureUnitDescriptor
->bUnitID
<< 8, &TransferBuffer
[0], sizeof(USHORT
), USBD_TRANSFER_DIRECTION_IN
);
283 /* get maximum value */
284 UsbAudioGetSetProperty(FilterContext
->DeviceExtension
->LowerDevice
, 0x83, 0x2 << 8, FeatureUnitDescriptor
->bUnitID
<< 8, &TransferBuffer
[1], sizeof(USHORT
), USBD_TRANSFER_DIRECTION_IN
);
286 if (TransferBuffer
[0] > Value
)
288 /* use minimum value */
289 Value
= TransferBuffer
[0];
292 if (TransferBuffer
[1] < Value
)
294 /* use maximum value */
295 Value
= TransferBuffer
[1];
299 TransferBuffer
[2] = Value
;
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
))
305 /* store number of bytes transferred*/
306 Irp
->IoStatus
.Information
= sizeof(LONG
);
311 /* free transfer buffer */
312 FreeFunction(TransferBuffer
);
319 CountTopologyComponents(
320 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
321 OUT PULONG OutDescriptorCount
)
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 PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR SelectorUnitDescriptor
;
330 ULONG NodeCount
= 0, Length
, Index
;
331 ULONG DescriptorCount
= 0;
334 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
336 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
338 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
340 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
341 if (InterfaceHeaderDescriptor
!= NULL
)
343 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
344 while (CommonDescriptor
)
346 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
347 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
352 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
354 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
357 /* get controls from all channels*/
359 Length
= FeatureUnitDescriptor
->bLength
- 7;
360 for (Index
= 0; Index
< Length
; Index
++)
362 Value
|= FeatureUnitDescriptor
->bmaControls
[Index
];
365 if (Value
& 0x01) /* MUTE*/
367 if (Value
& 0x02) /* VOLUME */
369 if (Value
& 0x04) /* BASS */
371 if (Value
& 0x08) /* MID */
373 if (Value
& 0x10) /* TREBLE */
375 if (Value
& 0x20) /* GRAPHIC EQUALIZER */
377 if (Value
& 0x40) /* AUTOMATIC GAIN */
379 if (Value
& 0x80) /* DELAY */
382 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
384 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
386 NodeCount
+= MixerUnitDescriptor
->bNrInPins
+ 1; /* KSNODETYPE_SUPERMIX for each source pin and KSNODETYPE_SUM for target */
388 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x05 /* SELECTOR_UNIT */)
390 SelectorUnitDescriptor
= (PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
398 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
399 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
405 *OutDescriptorCount
= DescriptorCount
;
410 FindNodeContextWithId(
411 IN PNODE_CONTEXT NodeContext
,
412 IN ULONG NodeContextCount
,
416 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
;
418 for (Index
= 0; Index
< NodeContextCount
; Index
++)
420 TerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)NodeContext
[Index
].Descriptor
;
421 if (TerminalDescriptor
->bTerminalID
== TerminalId
)
422 return &NodeContext
[Index
];
428 BuildUSBAudioFilterTopology(
430 PKSFILTER_DESCRIPTOR FilterDescriptor
)
432 PDEVICE_EXTENSION DeviceExtension
;
433 ULONG NodeCount
, Index
, DescriptorCount
, StreamingTerminalIndex
, NonStreamingTerminalDescriptorCount
, TotalTerminalDescriptorCount
, StreamingTerminalPinOffset
, ControlDescriptorCount
, Length
;
435 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
436 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
437 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
438 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
439 PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR FeatureUnitDescriptor
;
440 PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR MixerUnitDescriptor
;
441 PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR OutputTerminalDescriptor
;
442 PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR SelectorUnitDescriptor
;
443 PKSNODE_DESCRIPTOR NodeDescriptors
;
444 PNODE_CONTEXT NodeContext
, PreviousNodeContext
;
445 PKSTOPOLOGY_CONNECTION Connections
;
446 PKSAUTOMATION_TABLE AutomationTable
;
448 /* get device extension */
449 DeviceExtension
= Device
->Context
;
451 /* count topology nodes */
452 NodeCount
= CountTopologyComponents(DeviceExtension
->ConfigurationDescriptor
, &ControlDescriptorCount
);
454 /* init node descriptors*/
455 FilterDescriptor
->NodeDescriptors
= NodeDescriptors
= AllocFunction(NodeCount
* sizeof(KSNODE_DESCRIPTOR
));
456 if (FilterDescriptor
->NodeDescriptors
== NULL
)
459 return STATUS_INSUFFICIENT_RESOURCES
;
461 FilterDescriptor
->NodeDescriptorSize
= sizeof(KSNODE_DESCRIPTOR
);
463 DeviceExtension
->NodeContext
= NodeContext
= AllocFunction(sizeof(NODE_CONTEXT
) * ControlDescriptorCount
);
467 return STATUS_INSUFFICIENT_RESOURCES
;
469 DeviceExtension
->NodeContextCount
= ControlDescriptorCount
;
472 /* first enumerate all topology nodes */
473 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
475 Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
477 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
479 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
480 if (InterfaceHeaderDescriptor
!= NULL
)
482 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
483 while (CommonDescriptor
)
485 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
486 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/)
488 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
490 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SRC
;
491 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SRC
;
492 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
494 /* insert into node context*/
495 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
496 NodeContext
[DescriptorCount
].NodeCount
= 1;
497 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
500 FilterDescriptor
->NodeDescriptorsCount
++;
502 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x200)
504 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_ADC
;
505 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_ADC
;
506 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
508 /* insert into node context*/
509 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
510 NodeContext
[DescriptorCount
].NodeCount
= 1;
511 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
515 FilterDescriptor
->NodeDescriptorsCount
++;
517 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x300)
519 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_DAC
;
520 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_DAC
;
521 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
523 /* insert into node context*/
524 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
525 NodeContext
[DescriptorCount
].NodeCount
= 1;
526 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
529 FilterDescriptor
->NodeDescriptorsCount
++;
533 DPRINT1("Unexpected input terminal type %x\n", InputTerminalDescriptor
->wTerminalType
);
536 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
538 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
540 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SRC
;
541 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SRC
;
542 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
544 /* insert into node context*/
545 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
546 NodeContext
[DescriptorCount
].NodeCount
= 1;
547 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
550 FilterDescriptor
->NodeDescriptorsCount
++;
552 else if ((InputTerminalDescriptor
->wTerminalType
& 0xFF00) == 0x300)
554 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_DAC
;
555 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_DAC
;
556 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
558 /* insert into node context*/
559 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
560 NodeContext
[DescriptorCount
].NodeCount
= 1;
561 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
564 FilterDescriptor
->NodeDescriptorsCount
++;
568 DPRINT1("Unexpected output terminal type %x\n", InputTerminalDescriptor
->wTerminalType
);
572 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
574 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)CommonDescriptor
;
576 /* get controls from all channels*/
578 Length
= FeatureUnitDescriptor
->bLength
- 7;
579 for (Index
= 0; Index
< Length
; Index
++)
581 Value
|= FeatureUnitDescriptor
->bmaControls
[Index
];
585 if (Value
& 0x01) /* MUTE*/
587 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_MUTE
;
588 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_MUTE
;
589 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
592 AutomationTable
->PropertySets
= FilterAudioMutePropertySetArray
;
593 AutomationTable
->PropertySetsCount
= 1;
594 AutomationTable
->PropertyItemSize
= sizeof(KSPROPERTY_ITEM
);
597 /* insert into node context*/
598 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
599 NodeContext
[DescriptorCount
].NodeCount
++;
601 FilterDescriptor
->NodeDescriptorsCount
++;
603 if (Value
& 0x02) /* VOLUME */
605 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_VOLUME
;
606 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_VOLUME
;
607 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
610 AutomationTable
->PropertySets
= FilterAudioVolumePropertySetArray
;
611 AutomationTable
->PropertySetsCount
= 1;
612 AutomationTable
->PropertyItemSize
= sizeof(KSPROPERTY_ITEM
);
615 /* insert into node context*/
616 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
617 NodeContext
[DescriptorCount
].NodeCount
++;
619 FilterDescriptor
->NodeDescriptorsCount
++;
622 if (Value
& 0x04) /* BASS */
624 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
625 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
626 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
628 /* insert into node context*/
629 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
630 NodeContext
[DescriptorCount
].NodeCount
++;
632 FilterDescriptor
->NodeDescriptorsCount
++;
635 if (Value
& 0x08) /* MID */
637 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
638 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
639 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
641 /* insert into node context*/
642 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
643 NodeContext
[DescriptorCount
].NodeCount
++;
645 FilterDescriptor
->NodeDescriptorsCount
++;
648 if (Value
& 0x10) /* TREBLE */
650 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
651 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
652 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
654 /* insert into node context*/
655 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
656 NodeContext
[DescriptorCount
].NodeCount
++;
659 FilterDescriptor
->NodeDescriptorsCount
++;
662 if (Value
& 0x20) /* GRAPHIC EQUALIZER */
664 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
665 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
666 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
668 /* insert into node context*/
669 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
670 NodeContext
[DescriptorCount
].NodeCount
++;
672 FilterDescriptor
->NodeDescriptorsCount
++;
675 if (Value
& 0x40) /* AUTOMATIC GAIN */
677 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_AGC
;
678 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_AGC
;
679 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
681 /* insert into node context*/
682 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
683 NodeContext
[DescriptorCount
].NodeCount
++;
686 FilterDescriptor
->NodeDescriptorsCount
++;
689 if (Value
& 0x80) /* DELAY */
691 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_TONE
;
692 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_TONE
;
693 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
695 /* insert into node context*/
696 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
697 NodeContext
[DescriptorCount
].NodeCount
++;
699 FilterDescriptor
->NodeDescriptorsCount
++;
701 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
705 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
707 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)CommonDescriptor
;
708 for (Index
= 0; Index
< MixerUnitDescriptor
->bNrInPins
; Index
++)
710 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SUPERMIX
;
711 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SUPERMIX
;
712 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
714 /* insert into node context*/
715 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
716 NodeContext
[DescriptorCount
].NodeCount
++;
718 FilterDescriptor
->NodeDescriptorsCount
++;
721 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_SUM
;
722 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_SUM
;
723 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
725 /* insert into node context*/
726 NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
] = FilterDescriptor
->NodeDescriptorsCount
;
727 NodeContext
[DescriptorCount
].NodeCount
++;
728 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
731 FilterDescriptor
->NodeDescriptorsCount
++;
733 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x05 /* SELECTOR UNIT */)
735 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Type
= &KSNODETYPE_MUX
;
736 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].Name
= &KSNODETYPE_MUX
;
737 NodeDescriptors
[FilterDescriptor
->NodeDescriptorsCount
].AutomationTable
= AllocFunction(sizeof(KSAUTOMATION_TABLE
));
739 /* insert into node context*/
740 NodeContext
[DescriptorCount
].Descriptor
= CommonDescriptor
;
741 NodeContext
[DescriptorCount
].NodeCount
= 1;
742 NodeContext
[DescriptorCount
].Nodes
[0] = FilterDescriptor
->NodeDescriptorsCount
;
744 FilterDescriptor
->NodeDescriptorsCount
++;
750 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
751 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
758 /* FIXME determine connections count*/
759 FilterDescriptor
->Connections
= Connections
= AllocFunction(sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->NodeDescriptorsCount
* 2);
760 if (!FilterDescriptor
->Connections
)
763 return STATUS_INSUFFICIENT_RESOURCES
;
765 FilterDescriptor
->ConnectionsCount
= 0;
767 /* now build connections array */
769 StreamingTerminalIndex
= 0;
772 CountTerminalUnits(DeviceExtension
->ConfigurationDescriptor
, &NonStreamingTerminalDescriptorCount
, &TotalTerminalDescriptorCount
);
773 StreamingTerminalPinOffset
= TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
;
775 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
777 Descriptor
= USBD_ParseConfigurationDescriptorEx(DeviceExtension
->ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
779 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
781 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(DeviceExtension
->ConfigurationDescriptor
, DeviceExtension
->ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
782 if (InterfaceHeaderDescriptor
!= NULL
)
784 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
785 while (CommonDescriptor
)
787 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
788 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/)
790 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
792 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= KSFILTER_NODE
;
793 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= StreamingTerminalIndex
;
794 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
795 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
796 FilterDescriptor
->ConnectionsCount
++;
797 StreamingTerminalIndex
++;
802 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= KSFILTER_NODE
;
803 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= StreamingTerminalPinOffset
;
804 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
805 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
806 FilterDescriptor
->ConnectionsCount
++;
807 StreamingTerminalPinOffset
++;
811 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
813 OutputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
814 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, OutputTerminalDescriptor
->bSourceID
);
815 if (PreviousNodeContext
)
817 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
- 1];
818 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
819 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
820 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
821 FilterDescriptor
->ConnectionsCount
++;
824 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
826 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[0];
827 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
828 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= StreamingTerminalIndex
;
829 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= KSFILTER_NODE
;
830 FilterDescriptor
->ConnectionsCount
++;
831 StreamingTerminalIndex
++;
835 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[0];
836 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
837 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= StreamingTerminalPinOffset
;
838 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= KSFILTER_NODE
;
839 FilterDescriptor
->ConnectionsCount
++;
841 StreamingTerminalPinOffset
++;
845 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x06 /* FEATURE_UNIT*/)
847 FeatureUnitDescriptor
= (PUSB_AUDIO_CONTROL_FEATURE_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
848 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, FeatureUnitDescriptor
->bSourceID
);
849 if (PreviousNodeContext
)
851 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
-1];
852 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
853 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
854 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
855 FilterDescriptor
->ConnectionsCount
++;
857 for (Index
= 1; Index
< NodeContext
[DescriptorCount
].NodeCount
; Index
++)
859 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[Index
- 1];
860 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
861 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
862 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
863 FilterDescriptor
->ConnectionsCount
++;
868 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x04 /* MIXER_UNIT */)
870 MixerUnitDescriptor
= (PUSB_AUDIO_CONTROL_MIXER_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
871 for (Index
= 0; Index
< MixerUnitDescriptor
->bNrInPins
; Index
++)
873 Value
= MixerUnitDescriptor
->baSourceID
[Index
];
874 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, Value
);
875 if (PreviousNodeContext
)
877 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
- 1];
878 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
879 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
880 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
881 FilterDescriptor
->ConnectionsCount
++;
884 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= NodeContext
[DescriptorCount
].Nodes
[Index
];
885 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
886 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1 + Index
;
887 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[NodeContext
[DescriptorCount
].NodeCount
-1];
888 FilterDescriptor
->ConnectionsCount
++;
892 else if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x05 /* SELECTOR_UNIT */)
894 SelectorUnitDescriptor
= (PUSB_AUDIO_CONTROL_SELECTOR_UNIT_DESCRIPTOR
)InputTerminalDescriptor
;
895 for (Index
= 0; Index
< SelectorUnitDescriptor
->bNrInPins
; Index
++)
897 Value
= SelectorUnitDescriptor
->baSourceID
[Index
];
898 PreviousNodeContext
= FindNodeContextWithId(NodeContext
, ControlDescriptorCount
, Value
);
899 if (PreviousNodeContext
)
901 Connections
[FilterDescriptor
->ConnectionsCount
].FromNode
= PreviousNodeContext
->Nodes
[PreviousNodeContext
->NodeCount
- 1];
902 Connections
[FilterDescriptor
->ConnectionsCount
].FromNodePin
= 0;
903 Connections
[FilterDescriptor
->ConnectionsCount
].ToNodePin
= 1;
904 Connections
[FilterDescriptor
->ConnectionsCount
].ToNode
= NodeContext
[DescriptorCount
].Nodes
[0];
905 FilterDescriptor
->ConnectionsCount
++;
914 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
915 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
924 return STATUS_SUCCESS
;
929 USBAudioFilterCreate(
933 PKSFILTERFACTORY FilterFactory
;
935 PFILTER_CONTEXT FilterContext
;
937 FilterFactory
= KsGetParent(Filter
);
938 if (FilterFactory
== NULL
)
940 /* invalid parameter */
941 return STATUS_INVALID_PARAMETER
;
944 Device
= KsGetParent(FilterFactory
);
947 /* invalid parameter */
948 return STATUS_INVALID_PARAMETER
;
951 /* alloc filter context */
952 FilterContext
= AllocFunction(sizeof(FILTER_CONTEXT
));
953 if (FilterContext
== NULL
)
956 return STATUS_INSUFFICIENT_RESOURCES
;
960 FilterContext
->DeviceExtension
= Device
->Context
;
961 FilterContext
->LowerDevice
= Device
->NextDeviceObject
;
962 Filter
->Context
= FilterContext
;
964 DPRINT("USBAudioFilterCreate FilterContext %p LowerDevice %p DeviceExtension %p\n", FilterContext
, FilterContext
->LowerDevice
, FilterContext
->DeviceExtension
);
965 KsAddItemToObjectBag(Filter
->Bag
, FilterContext
, ExFreePool
);
966 return STATUS_SUCCESS
;
973 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
974 OUT PULONG NonStreamingTerminalDescriptorCount
,
975 OUT PULONG TotalTerminalDescriptorCount
)
977 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
978 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
979 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
980 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
981 ULONG NonStreamingTerminalCount
= 0;
982 ULONG TotalTerminalCount
= 0;
984 for(Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
986 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
988 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
990 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
991 if (InterfaceHeaderDescriptor
!= NULL
)
993 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
994 while (CommonDescriptor
)
996 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
997 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
999 if (InputTerminalDescriptor
->wTerminalType
!= USB_AUDIO_STREAMING_TERMINAL_TYPE
)
1001 NonStreamingTerminalCount
++;
1003 TotalTerminalCount
++;
1005 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
1006 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
1011 else if (Descriptor
->bInterfaceSubClass
== 0x03) /* MIDI_STREAMING */
1016 *NonStreamingTerminalDescriptorCount
= NonStreamingTerminalCount
;
1017 *TotalTerminalDescriptorCount
= TotalTerminalCount
;
1021 UsbAudioGetPinCategoryFromTerminalDescriptor(
1022 IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
)
1024 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_MICROPHONE_TERMINAL_TYPE
)
1025 return &NodeTypeMicrophone
;
1026 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE
)
1027 return &NodeTypeDesktopMicrophone
;
1028 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE
)
1029 return &NodeTypePersonalMicrophone
;
1030 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE
)
1031 return &NodeTypeOmmniMicrophone
;
1032 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE
)
1033 return &NodeTypeArrayMicrophone
;
1034 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE
)
1035 return &NodeTypeProcessingArrayMicrophone
;
1037 /* playback types */
1038 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_SPEAKER_TERMINAL_TYPE
)
1039 return &NodeTypeSpeaker
;
1040 else if (TerminalDescriptor
->wTerminalType
== USB_HEADPHONES_SPEAKER_TERMINAL_TYPE
)
1041 return &NodeTypeHeadphonesSpeaker
;
1042 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_HMDA_TERMINAL_TYPE
)
1043 return &NodeTypeHMDA
;
1044 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE
)
1045 return &NodeTypeDesktopSpeaker
;
1046 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE
)
1047 return &NodeTypeRoomSpeaker
;
1048 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE
)
1049 return &NodeTypeCommunicationSpeaker
;
1050 else if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_SUBWOOFER_TERMINAL_TYPE
)
1051 return &NodeTypeSubwoofer
;
1053 if (TerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
1055 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
1056 return &NodeTypeCapture
;
1057 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
1058 return &NodeTypePlayback
;
1064 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
1065 UsbAudioGetStreamingTerminalDescriptorByIndex(
1066 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
1069 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
1070 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
1071 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
1072 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
1073 ULONG TerminalCount
= 0;
1075 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
1077 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
1079 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
1081 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1082 if (InterfaceHeaderDescriptor
!= NULL
)
1084 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1085 while (CommonDescriptor
)
1087 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
1088 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
1090 if (InputTerminalDescriptor
->wTerminalType
== USB_AUDIO_STREAMING_TERMINAL_TYPE
)
1092 if (TerminalCount
== Index
)
1094 return InputTerminalDescriptor
;
1099 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
1100 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
1109 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
1110 UsbAudioGetNonStreamingTerminalDescriptorByIndex(
1111 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
1115 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
1116 PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR InterfaceHeaderDescriptor
;
1117 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
1118 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR InputTerminalDescriptor
;
1119 ULONG TerminalCount
= 0;
1121 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
1123 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
1125 if (Descriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL */
1127 InterfaceHeaderDescriptor
= (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1128 if (InterfaceHeaderDescriptor
!= NULL
)
1130 CommonDescriptor
= USBD_ParseDescriptors(InterfaceHeaderDescriptor
, InterfaceHeaderDescriptor
->wTotalLength
, (PVOID
)((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->bLength
), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1131 while (CommonDescriptor
)
1133 InputTerminalDescriptor
= (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
)CommonDescriptor
;
1134 if (InputTerminalDescriptor
->bDescriptorSubtype
== 0x02 /* INPUT TERMINAL*/ || InputTerminalDescriptor
->bDescriptorSubtype
== 0x03 /* OUTPUT_TERMINAL*/)
1136 if (InputTerminalDescriptor
->wTerminalType
!= USB_AUDIO_STREAMING_TERMINAL_TYPE
)
1138 if (TerminalCount
== Index
)
1140 return InputTerminalDescriptor
;
1145 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
1146 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)InterfaceHeaderDescriptor
+ InterfaceHeaderDescriptor
->wTotalLength
))
1156 UsbAudioGetDataRanges(
1157 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
1158 IN UCHAR bTerminalID
,
1159 OUT PKSDATARANGE
** OutDataRanges
,
1160 OUT PULONG OutDataRangesCount
)
1162 PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor
;
1163 PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR StreamingFormatDescriptor
;
1164 PUSB_INTERFACE_DESCRIPTOR Descriptor
;
1165 PKSDATARANGE_AUDIO DataRangeAudio
;
1166 PKSDATARANGE
*DataRangeAudioArray
;
1167 ULONG NumFrequency
, DataRangeCount
, DataRangeIndex
, Index
;
1169 /* count all data ranges */
1171 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
1173 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
1175 if (Descriptor
->bInterfaceSubClass
== 0x02) /* AUDIO_STREAMING */
1177 StreamingInterfaceDescriptor
= (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1178 if (StreamingInterfaceDescriptor
!= NULL
)
1180 ASSERT(StreamingInterfaceDescriptor
->bDescriptorSubtype
== 0x01);
1181 ASSERT(StreamingInterfaceDescriptor
->wFormatTag
== WAVE_FORMAT_PCM
);
1182 if (StreamingInterfaceDescriptor
->bTerminalLink
== bTerminalID
)
1185 DPRINT1("StreamingInterfaceDescriptor %p TerminalID %x\n", StreamingInterfaceDescriptor
, bTerminalID
);
1188 Descriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StreamingInterfaceDescriptor
;
1192 DataRangeAudioArray
= AllocFunction(sizeof(PVOID
) * DataRangeCount
);
1193 if (DataRangeAudioArray
== NULL
)
1200 for (Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
1202 Descriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)Descriptor
+ Descriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1))
1204 if (Descriptor
->bInterfaceSubClass
== 0x02) /* AUDIO_STREAMING */
1206 StreamingInterfaceDescriptor
= (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR
)USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, Descriptor
, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE
);
1207 if (StreamingInterfaceDescriptor
!= NULL
)
1209 ASSERT(StreamingInterfaceDescriptor
->bDescriptorSubtype
== 0x01);
1210 ASSERT(StreamingInterfaceDescriptor
->wFormatTag
== WAVE_FORMAT_PCM
);
1211 if (StreamingInterfaceDescriptor
->bTerminalLink
== bTerminalID
)
1213 StreamingFormatDescriptor
= (PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR
)((ULONG_PTR
)StreamingInterfaceDescriptor
+ StreamingInterfaceDescriptor
->bLength
);
1214 ASSERT(StreamingFormatDescriptor
->bDescriptorType
== 0x24);
1215 ASSERT(StreamingFormatDescriptor
->bDescriptorSubtype
== 0x02);
1216 ASSERT(StreamingFormatDescriptor
->bFormatType
== 0x01);
1218 DataRangeAudio
= AllocFunction(sizeof(KSDATARANGE_AUDIO
));
1219 if (DataRangeAudio
== NULL
)
1225 DataRangeAudio
->DataRange
.FormatSize
= sizeof(KSDATARANGE_AUDIO
);
1226 DataRangeAudio
->DataRange
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
1227 DataRangeAudio
->DataRange
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
1228 DataRangeAudio
->DataRange
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
1229 DataRangeAudio
->MaximumChannels
= StreamingFormatDescriptor
->bNrChannels
;
1230 DataRangeAudio
->MinimumBitsPerSample
= StreamingFormatDescriptor
->bBitResolution
;
1231 DataRangeAudio
->MaximumBitsPerSample
= StreamingFormatDescriptor
->bBitResolution
;
1232 NumFrequency
= StreamingFormatDescriptor
->bSamFreqType
;
1233 DataRangeAudio
->MinimumSampleFrequency
= MAXULONG
;
1234 DataRangeAudio
->MaximumSampleFrequency
= 0;
1235 for (Index
= 0; Index
< NumFrequency
; Index
++)
1237 DataRangeAudio
->MinimumSampleFrequency
= min(StreamingFormatDescriptor
->tSamFreq
[Index
* 3] | StreamingFormatDescriptor
->tSamFreq
[(Index
* 3) + 1] << 8 | StreamingFormatDescriptor
->tSamFreq
[(Index
* 3) + 2] << 16, DataRangeAudio
->MinimumSampleFrequency
);
1238 DataRangeAudio
->MaximumSampleFrequency
= max(StreamingFormatDescriptor
->tSamFreq
[Index
* 3] | StreamingFormatDescriptor
->tSamFreq
[(Index
* 3) + 1] << 8 | StreamingFormatDescriptor
->tSamFreq
[(Index
* 3) + 2] << 16, DataRangeAudio
->MaximumSampleFrequency
);
1240 DataRangeAudioArray
[DataRangeIndex
] = (PKSDATARANGE
)DataRangeAudio
;
1244 Descriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StreamingInterfaceDescriptor
;
1248 *OutDataRanges
= DataRangeAudioArray
;
1249 *OutDataRangesCount
= DataRangeCount
;
1254 USBAudioPinBuildDescriptors(
1256 PKSPIN_DESCRIPTOR_EX
*PinDescriptors
,
1257 PULONG PinDescriptorsCount
,
1258 PULONG PinDescriptorSize
)
1260 PDEVICE_EXTENSION DeviceExtension
;
1261 PKSPIN_DESCRIPTOR_EX Pins
;
1262 ULONG TotalTerminalDescriptorCount
= 0;
1263 ULONG NonStreamingTerminalDescriptorCount
= 0;
1265 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor
= NULL
;
1267 /* get device extension */
1268 DeviceExtension
= Device
->Context
;
1270 CountTerminalUnits(DeviceExtension
->ConfigurationDescriptor
, &NonStreamingTerminalDescriptorCount
, &TotalTerminalDescriptorCount
);
1271 DPRINT("TotalTerminalDescriptorCount %lu NonStreamingTerminalDescriptorCount %lu\n", TotalTerminalDescriptorCount
, NonStreamingTerminalDescriptorCount
);
1274 Pins
= AllocFunction(sizeof(KSPIN_DESCRIPTOR_EX
) * TotalTerminalDescriptorCount
);
1278 return STATUS_INSUFFICIENT_RESOURCES
;
1281 for (Index
= 0; Index
< TotalTerminalDescriptorCount
; Index
++)
1283 if (Index
< (TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
))
1286 TerminalDescriptor
= UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension
->ConfigurationDescriptor
, Index
);
1287 ASSERT(TerminalDescriptor
!= NULL
);
1289 Pins
[Index
].Dispatch
= &UsbAudioPinDispatch
;
1290 Pins
[Index
].PinDescriptor
.InterfacesCount
= 1;
1291 Pins
[Index
].PinDescriptor
.Interfaces
= &StandardPinInterface
;
1292 Pins
[Index
].PinDescriptor
.MediumsCount
= 1;
1293 Pins
[Index
].PinDescriptor
.Mediums
= &StandardPinMedium
;
1294 Pins
[Index
].PinDescriptor
.Category
= UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor
);
1295 UsbAudioGetDataRanges(DeviceExtension
->ConfigurationDescriptor
, TerminalDescriptor
->bTerminalID
, (PKSDATARANGE
**)&Pins
[Index
].PinDescriptor
.DataRanges
, &Pins
[Index
].PinDescriptor
.DataRangesCount
);
1297 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
1299 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_BOTH
;
1300 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_OUT
;
1303 Pins
[Index
].Flags
= KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
| KSFILTER_FLAG_CRITICAL_PROCESSING
;
1305 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
1307 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_SINK
;
1308 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_IN
;
1311 Pins
[Index
].Flags
= KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
| KSPIN_FLAG_GENERATE_EOS_EVENTS
;
1314 /* data intersect handler */
1315 Pins
[Index
].IntersectHandler
= UsbAudioPinDataIntersect
;
1317 /* irp sinks / sources can be instantiated */
1318 Pins
[Index
].InstancesPossible
= 1;
1323 TerminalDescriptor
= UsbAudioGetNonStreamingTerminalDescriptorByIndex(DeviceExtension
->ConfigurationDescriptor
, Index
- (TotalTerminalDescriptorCount
- NonStreamingTerminalDescriptorCount
));
1324 Pins
[Index
].PinDescriptor
.InterfacesCount
= 1;
1325 Pins
[Index
].PinDescriptor
.Interfaces
= &StandardPinInterface
;
1326 Pins
[Index
].PinDescriptor
.MediumsCount
= 1;
1327 Pins
[Index
].PinDescriptor
.Mediums
= &StandardPinMedium
;
1328 Pins
[Index
].PinDescriptor
.DataRanges
= BridgePinAudioFormats
;
1329 Pins
[Index
].PinDescriptor
.DataRangesCount
= 1;
1330 Pins
[Index
].PinDescriptor
.Communication
= KSPIN_COMMUNICATION_BRIDGE
;
1331 Pins
[Index
].PinDescriptor
.Category
= UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor
);
1333 if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_INPUT_TERMINAL
)
1335 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_IN
;
1337 else if (TerminalDescriptor
->bDescriptorSubtype
== USB_AUDIO_OUTPUT_TERMINAL
)
1339 Pins
[Index
].PinDescriptor
.DataFlow
= KSPIN_DATAFLOW_OUT
;
1345 *PinDescriptors
= Pins
;
1346 *PinDescriptorSize
= sizeof(KSPIN_DESCRIPTOR_EX
);
1347 *PinDescriptorsCount
= TotalTerminalDescriptorCount
;
1349 return STATUS_SUCCESS
;
1354 USBAudioGetDescriptor(
1355 IN PDEVICE_OBJECT DeviceObject
,
1356 IN UCHAR DescriptorType
,
1357 IN ULONG DescriptorLength
,
1358 IN UCHAR DescriptorIndex
,
1359 IN LANGID LanguageId
,
1360 OUT PVOID
*OutDescriptor
)
1367 ASSERT(DeviceObject
);
1368 ASSERT(OutDescriptor
);
1369 ASSERT(DescriptorLength
);
1372 // first allocate descriptor buffer
1374 Descriptor
= AllocFunction(DescriptorLength
);
1378 return STATUS_INSUFFICIENT_RESOURCES
;
1382 Urb
= (PURB
)AllocFunction(sizeof(URB
));
1386 FreeFunction(Descriptor
);
1387 return STATUS_INSUFFICIENT_RESOURCES
;
1390 /* initialize urb */
1391 UsbBuildGetDescriptorRequest(Urb
,
1392 sizeof(Urb
->UrbControlDescriptorRequest
),
1402 Status
= SubmitUrbSync(DeviceObject
, Urb
);
1407 if (NT_SUCCESS(Status
))
1410 *OutDescriptor
= Descriptor
;
1415 FreeFunction(Descriptor
);
1424 USBAudioGetStringDescriptor(
1425 IN PDEVICE_OBJECT DeviceObject
,
1426 IN ULONG DescriptorLength
,
1427 IN UCHAR DescriptorIndex
,
1428 IN LANGID LanguageId
,
1429 OUT PVOID
*OutDescriptor
)
1433 /* retrieve descriptor */
1434 Status
= USBAudioGetDescriptor(DeviceObject
, USB_STRING_DESCRIPTOR_TYPE
, DescriptorLength
, DescriptorIndex
, LanguageId
, OutDescriptor
);
1435 if (!NT_SUCCESS(Status
))
1440 return STATUS_SUCCESS
;
1444 USBAudioRegCreateMediaCategoriesKey(
1445 IN PUNICODE_STRING Name
,
1446 OUT PHANDLE OutHandle
)
1449 OBJECT_ATTRIBUTES ObjectAttributes
;
1450 UNICODE_STRING DestinationString
;
1453 /* initialize root name*/
1454 RtlInitUnicodeString(&DestinationString
, L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
1456 /* initialize object attributes */
1457 InitializeObjectAttributes(&ObjectAttributes
, &DestinationString
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1459 /* create the key */
1460 Status
= ZwOpenKey(&Handle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1461 if (NT_SUCCESS(Status
))
1463 /* initialize object attributes */
1464 InitializeObjectAttributes(&ObjectAttributes
, Name
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, Handle
, NULL
);
1466 Status
= ZwCreateKey(OutHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1475 USBAudioInitComponentId(
1477 IN PKSCOMPONENTID ComponentId
)
1479 PDEVICE_EXTENSION DeviceExtension
;
1481 LPWSTR DescriptionBuffer
;
1482 UNICODE_STRING GuidString
;
1483 UNICODE_STRING Name
;
1487 /* get device extension */
1488 DeviceExtension
= Device
->Context
;
1490 /* init component id */
1491 ComponentId
->Component
= KSCOMPONENTID_USBAUDIO
;
1492 ComponentId
->Version
= HIBYTE(DeviceExtension
->DeviceDescriptor
->bcdDevice
);
1493 ComponentId
->Revision
= LOBYTE(DeviceExtension
->DeviceDescriptor
->bcdDevice
);
1495 INIT_USBAUDIO_MID(&ComponentId
->Manufacturer
, DeviceExtension
->DeviceDescriptor
->idVendor
);
1496 INIT_USBAUDIO_PID(&ComponentId
->Product
, DeviceExtension
->DeviceDescriptor
->idProduct
);
1497 INIT_USBAUDIO_PRODUCT_NAME(&TempGuid
, DeviceExtension
->DeviceDescriptor
->idVendor
, DeviceExtension
->DeviceDescriptor
->idProduct
, 0);
1499 if (DeviceExtension
->DeviceDescriptor
->iProduct
)
1501 Status
= USBAudioGetStringDescriptor(DeviceExtension
->LowerDevice
, 100 * sizeof(WCHAR
), DeviceExtension
->DeviceDescriptor
->iProduct
, 0x0409 /* FIXME */, (PVOID
*)&DescriptionBuffer
);
1502 if (NT_SUCCESS(Status
))
1504 Status
= RtlStringFromGUID(&TempGuid
, &GuidString
);
1505 if (NT_SUCCESS(Status
))
1507 Status
= USBAudioRegCreateMediaCategoriesKey(&GuidString
, &hKey
);
1508 if (NT_SUCCESS(Status
))
1510 RtlInitUnicodeString(&Name
, L
"Name");
1511 ZwSetValueKey(hKey
, &Name
, 0, REG_SZ
, DescriptionBuffer
, (wcslen(DescriptionBuffer
) + 1) * sizeof(WCHAR
));
1514 INIT_USBAUDIO_PRODUCT_NAME(&ComponentId
->Name
, DeviceExtension
->DeviceDescriptor
->idVendor
, DeviceExtension
->DeviceDescriptor
->idProduct
, 0);
1516 RtlFreeUnicodeString(&GuidString
);
1518 FreeFunction(DescriptionBuffer
);
1521 return STATUS_SUCCESS
;
1527 USBAudioCreateFilterContext(
1530 PKSFILTER_DESCRIPTOR FilterDescriptor
;
1531 PKSCOMPONENTID ComponentId
;
1534 /* allocate descriptor */
1535 FilterDescriptor
= AllocFunction(sizeof(KSFILTER_DESCRIPTOR
));
1536 if (!FilterDescriptor
)
1539 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
1542 /* init filter descriptor*/
1543 FilterDescriptor
->Version
= KSFILTER_DESCRIPTOR_VERSION
;
1544 FilterDescriptor
->Flags
= 0;
1545 FilterDescriptor
->ReferenceGuid
= &KSNAME_Filter
;
1546 FilterDescriptor
->Dispatch
= &USBAudioFilterDispatch
;
1547 FilterDescriptor
->CategoriesCount
= 1;
1548 FilterDescriptor
->Categories
= &GUID_KSCATEGORY_AUDIO
;
1550 /* init component id*/
1551 ComponentId
= AllocFunction(sizeof(KSCOMPONENTID
));
1555 return STATUS_INSUFFICIENT_RESOURCES
;
1557 Status
= USBAudioInitComponentId(Device
, ComponentId
);
1558 if (!NT_SUCCESS(Status
))
1561 FreeFunction(ComponentId
);
1564 FilterDescriptor
->ComponentId
= ComponentId
;
1566 /* build pin descriptors */
1567 Status
= USBAudioPinBuildDescriptors(Device
, (PKSPIN_DESCRIPTOR_EX
*)&FilterDescriptor
->PinDescriptors
, &FilterDescriptor
->PinDescriptorsCount
, &FilterDescriptor
->PinDescriptorSize
);
1568 if (!NT_SUCCESS(Status
))
1571 FreeFunction(ComponentId
);
1575 /* build topology */
1576 Status
= BuildUSBAudioFilterTopology(Device
, FilterDescriptor
);
1577 if (!NT_SUCCESS(Status
))
1580 FreeFunction(ComponentId
);
1584 /* lets create the filter */
1585 Status
= KsCreateFilterFactory(Device
->FunctionalDeviceObject
, FilterDescriptor
, ReferenceString
, NULL
, KSCREATE_ITEM_FREEONSTOP
, NULL
, NULL
, NULL
);
1586 DPRINT("KsCreateFilterFactory: %x\n", Status
);