2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/deviface.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
11 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
12 const GUID KSPROPSETID_Connection
= {0x1D58C920L
, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
13 const GUID KSPROPSETID_Sysaudio
= {0xCBE3FAA0L
, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
14 const GUID KSPROPSETID_General
= {0x1464EDA5L
, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
15 const GUID KSINTERFACESETID_Standard
= {0x1A8766A0L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
16 const GUID KSMEDIUMSETID_Standard
= {0x4747B320L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
17 const GUID KSDATAFORMAT_TYPE_AUDIO
= {0x73647561L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
18 const GUID KSDATAFORMAT_SUBTYPE_PCM
= {0x00000001L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
19 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
= {0x05589f81L
, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
20 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
28 Irp
->IoStatus
.Information
= Length
;
29 Irp
->IoStatus
.Status
= Status
;
30 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
37 IN PDEVICE_OBJECT DeviceObject
,
38 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
39 IN PWDMAUD_CLIENT ClientInfo
,
44 ULONG Count
, BytesReturned
, Index
, SubIndex
, Result
, NumPins
;
46 KSPIN_COMMUNICATION Communication
;
47 KSPIN_DATAFLOW DataFlow
;
48 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
50 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
52 DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo
->DeviceType
);
53 return STATUS_UNSUCCESSFUL
;
56 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
57 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
58 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
60 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
62 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
63 if (!NT_SUCCESS(Status
))
64 return STATUS_UNSUCCESSFUL
;
67 for(Index
= 0; Index
< Count
; Index
++)
69 /* query number of pins */
70 Pin
.Reserved
= Index
; // see sysaudio
71 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
72 Pin
.Property
.Set
= KSPROPSETID_Pin
;
73 Pin
.Property
.Id
= KSPROPERTY_PIN_CTYPES
;
76 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&NumPins
, sizeof(ULONG
), &BytesReturned
);
77 if (NT_SUCCESS(Status
))
79 /* enumerate now all pins */
80 for(SubIndex
= 0; SubIndex
< NumPins
; SubIndex
++)
83 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
84 Communication
= KSPIN_COMMUNICATION_NONE
;
86 /* get pin communication type */
87 KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
89 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
92 /* get pin dataflow type */
93 KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
95 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
97 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_IN
)
99 if(DeviceInfo
->DeviceIndex
== Result
)
101 /* found the index */
104 return STATUS_SUCCESS
;
110 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
112 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_OUT
)
114 if(DeviceInfo
->DeviceIndex
== Result
)
116 /* found the index */
119 return STATUS_SUCCESS
;
128 return STATUS_UNSUCCESSFUL
;
133 IN PDEVICE_OBJECT DeviceObject
,
135 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
136 IN PWDMAUD_CLIENT ClientInfo
)
138 PSYSAUDIO_INSTANCE_INFO InstanceInfo
;
139 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
142 ACCESS_MASK DesiredAccess
= 0;
144 KSPIN_CONNECT
* PinConnect
;
146 KSDATAFORMAT_WAVEFORMATEX
* DataFormat
;
151 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
153 return WdmAudControlOpenMixer(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
156 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
158 DPRINT1("FIXME: only waveout / wavein devices are supported\n");
159 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
162 Status
= GetFilterIdAndPinId(DeviceObject
, DeviceInfo
, ClientInfo
, &FilterId
, &PinId
);
163 if (!NT_SUCCESS(Status
))
165 DPRINT1("Invalid device index %u\n", DeviceInfo
->DeviceIndex
);
166 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
169 /* close pin handle which uses same virtual audio device id and pin id */
170 FreeIndex
= (ULONG
)-1;
171 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
173 if (ClientInfo
->hPins
[Index
].FilterId
== FilterId
&& ClientInfo
->hPins
[Index
].PinId
== PinId
&& ClientInfo
->hPins
[Index
].Handle
&& ClientInfo
->hPins
[Index
].Type
== DeviceInfo
->DeviceType
)
175 ZwClose(ClientInfo
->hPins
[Index
].Handle
);
176 ClientInfo
->hPins
[Index
].Handle
= NULL
;
182 Length
= sizeof(KSDATAFORMAT_WAVEFORMATEX
) + sizeof(KSPIN_CONNECT
) + sizeof(SYSAUDIO_INSTANCE_INFO
);
183 InstanceInfo
= ExAllocatePool(NonPagedPool
, Length
);
187 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
190 InstanceInfo
->Property
.Set
= KSPROPSETID_Sysaudio
;
191 InstanceInfo
->Property
.Id
= KSPROPERTY_SYSAUDIO_INSTANCE_INFO
;
192 InstanceInfo
->Property
.Flags
= KSPROPERTY_TYPE_SET
;
193 InstanceInfo
->Flags
= 0;
194 InstanceInfo
->DeviceNumber
= FilterId
;
196 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
197 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
||
198 DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
||
199 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
201 DesiredAccess
|= GENERIC_READ
;
204 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
||
205 DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
||
206 DeviceInfo
->DeviceType
== AUX_DEVICE_TYPE
||
207 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
209 DesiredAccess
|= GENERIC_WRITE
;
212 PinConnect
= (KSPIN_CONNECT
*)(InstanceInfo
+ 1);
215 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
216 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
217 PinConnect
->Interface
.Flags
= 0;
218 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
219 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
220 PinConnect
->Medium
.Flags
= 0;
221 PinConnect
->PinId
= PinId
;
222 PinConnect
->PinToHandle
= DeviceExtension
->hSysAudio
;
223 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
224 PinConnect
->Priority
.PrioritySubClass
= 1;
227 DataFormat
= (KSDATAFORMAT_WAVEFORMATEX
*) (PinConnect
+ 1);
228 DataFormat
->WaveFormatEx
.wFormatTag
= DeviceInfo
->u
.WaveFormatEx
.wFormatTag
;
229 DataFormat
->WaveFormatEx
.nChannels
= DeviceInfo
->u
.WaveFormatEx
.nChannels
;
230 DataFormat
->WaveFormatEx
.nSamplesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nSamplesPerSec
;
231 DataFormat
->WaveFormatEx
.nBlockAlign
= DeviceInfo
->u
.WaveFormatEx
.nBlockAlign
;
232 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nAvgBytesPerSec
;
233 DataFormat
->WaveFormatEx
.wBitsPerSample
= DeviceInfo
->u
.WaveFormatEx
.wBitsPerSample
;
234 DataFormat
->WaveFormatEx
.cbSize
= 0;
235 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
236 DataFormat
->DataFormat
.Flags
= 0;
237 DataFormat
->DataFormat
.Reserved
= 0;
238 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
240 if (DeviceInfo
->u
.WaveFormatEx
.wFormatTag
!= WAVE_FORMAT_PCM
)
243 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
244 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
245 DataFormat
->DataFormat
.SampleSize
= 4;
247 /* ros specific pin creation request */
248 InstanceInfo
->Property
.Id
= (ULONG
)-1;
249 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, Length
, &PinHandle
, sizeof(HANDLE
), &BytesReturned
);
250 if (NT_SUCCESS(Status
))
252 PWDMAUD_HANDLE Handels
;
254 if (FreeIndex
!= (ULONG
)-1)
256 /* re-use a free index */
257 ClientInfo
->hPins
[Index
].Handle
= PinHandle
;
258 ClientInfo
->hPins
[Index
].FilterId
= FilterId
;
259 ClientInfo
->hPins
[Index
].PinId
= PinId
;
260 ClientInfo
->hPins
[Index
].Type
= DeviceInfo
->DeviceType
;
262 DeviceInfo
->hDevice
= PinHandle
;
263 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
266 Handels
= ExAllocatePool(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
270 if (ClientInfo
->NumPins
)
272 RtlMoveMemory(Handels
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
273 ExFreePool(ClientInfo
->hPins
);
276 ClientInfo
->hPins
= Handels
;
277 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= PinHandle
;
278 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= DeviceInfo
->DeviceType
;
279 ClientInfo
->hPins
[ClientInfo
->NumPins
].FilterId
= FilterId
;
280 ClientInfo
->hPins
[ClientInfo
->NumPins
].PinId
= PinId
;
281 ClientInfo
->NumPins
++;
283 DeviceInfo
->hDevice
= PinHandle
;
287 DeviceInfo
->hDevice
= NULL
;
290 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
294 WdmAudControlDeviceType(
295 IN PDEVICE_OBJECT DeviceObject
,
297 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
298 IN PWDMAUD_CLIENT ClientInfo
)
301 ULONG Count
, BytesReturned
, Index
, SubIndex
, Result
, NumPins
;
303 KSPIN_COMMUNICATION Communication
;
304 KSPIN_DATAFLOW DataFlow
;
305 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
307 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
309 DeviceInfo
->DeviceCount
= GetNumOfMixerDevices(DeviceObject
);
310 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
313 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
315 DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo
->DeviceType
);
316 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
319 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
320 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
321 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
323 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
324 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
325 if (!NT_SUCCESS(Status
))
327 DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status
);
328 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
331 /* now enumerate all available filters */
332 for(Index
= 0; Index
< Count
; Index
++)
334 /* query number of pins */
335 Pin
.Reserved
= Index
; // see sysaudio
336 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
337 Pin
.Property
.Set
= KSPROPSETID_Pin
;
338 Pin
.Property
.Id
= KSPROPERTY_PIN_CTYPES
;
341 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&NumPins
, sizeof(ULONG
), &BytesReturned
);
342 if (NT_SUCCESS(Status
))
344 /* enumerate now all pins */
345 for(SubIndex
= 0; SubIndex
< NumPins
; SubIndex
++)
347 Pin
.PinId
= SubIndex
;
348 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
349 Communication
= KSPIN_COMMUNICATION_NONE
;
351 /* get pin communication type */
352 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
353 if (!NT_SUCCESS(Status
))
356 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
359 /* get pin dataflow type */
360 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
361 if (!NT_SUCCESS(Status
))
364 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
366 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_IN
)
369 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
371 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_OUT
)
378 /* store result count */
379 DeviceInfo
->DeviceCount
= Result
;
381 DPRINT1("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
382 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
386 WdmAudControlDeviceState(
387 IN PDEVICE_OBJECT DeviceObject
,
389 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
390 IN PWDMAUD_CLIENT ClientInfo
)
396 PFILE_OBJECT FileObject
;
398 //DPRINT1("WdmAudControlDeviceState\n");
400 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
401 if (!NT_SUCCESS(Status
))
403 DPRINT1("Error: invalid device handle provided %p\n", DeviceInfo
->hDevice
);
404 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
407 Property
.Set
= KSPROPSETID_Connection
;
408 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
409 Property
.Flags
= KSPROPERTY_TYPE_SET
;
411 State
= DeviceInfo
->u
.State
;
413 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
415 ObDereferenceObject(FileObject
);
417 //DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
418 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
423 IN PKSDATARANGE_AUDIO DataRangeAudio
,
424 ULONG SampleFrequency
,
432 if (DataRangeAudio
->MinimumSampleFrequency
<= SampleFrequency
&& DataRangeAudio
->MaximumSampleFrequency
>= SampleFrequency
)
434 if (DataRangeAudio
->MinimumBitsPerSample
<= 8 && DataRangeAudio
->MaximumBitsPerSample
>= 8)
437 if (DataRangeAudio
->MaximumChannels
>= 2)
439 Result
|= Stereo8Bit
;
443 if (DataRangeAudio
->MinimumBitsPerSample
<= 16 && DataRangeAudio
->MaximumBitsPerSample
>= 16)
446 if (DataRangeAudio
->MaximumChannels
>= 2)
448 Result
|= Stereo8Bit
;
458 IN PDEVICE_OBJECT DeviceObject
,
460 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
461 IN PWDMAUD_CLIENT ClientInfo
)
463 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
464 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
466 KSCOMPONENTID ComponentId
;
467 KSMULTIPLE_ITEM
* MultipleItem
;
469 PKSDATARANGE_AUDIO DataRangeAudio
;
470 PKSDATARANGE DataRange
;
478 DPRINT("WdmAudCapabilities entered\n");
480 Status
= GetFilterIdAndPinId(DeviceObject
, DeviceInfo
, ClientInfo
, &FilterId
, &PinId
);
481 if (!NT_SUCCESS(Status
))
483 DPRINT1("Invalid device index provided %u\n", DeviceInfo
->DeviceIndex
);
484 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
487 PinProperty
.PinId
= FilterId
;
488 PinProperty
.Property
.Set
= KSPROPSETID_Sysaudio
;
489 PinProperty
.Property
.Id
= KSPROPERTY_SYSAUDIO_COMPONENT_ID
;
490 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
492 RtlZeroMemory(&ComponentId
, sizeof(KSCOMPONENTID
));
494 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
495 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)&ComponentId
, sizeof(KSCOMPONENTID
), &BytesReturned
);
496 if (NT_SUCCESS(Status
))
498 DeviceInfo
->u
.WaveOutCaps
.wMid
= ComponentId
.Manufacturer
.Data1
- 0xd5a47fa7;
499 DeviceInfo
->u
.WaveOutCaps
.vDriverVersion
= MAKELONG(ComponentId
.Version
, ComponentId
.Revision
);
502 PinProperty
.Reserved
= DeviceInfo
->DeviceIndex
;
503 PinProperty
.PinId
= PinId
;
504 PinProperty
.Property
.Set
= KSPROPSETID_Pin
;
505 PinProperty
.Property
.Id
= KSPROPERTY_PIN_DATARANGES
;
506 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
509 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)NULL
, 0, &BytesReturned
);
510 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
512 return SetIrpIoStatus(Irp
, Status
, 0);
515 MultipleItem
= ExAllocatePool(NonPagedPool
, BytesReturned
);
519 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
522 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
523 if (!NT_SUCCESS(Status
))
525 ExFreePool(MultipleItem
);
526 return SetIrpIoStatus(Irp
, Status
, 0);
529 DataRange
= (PKSDATARANGE
) (MultipleItem
+ 1);
530 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
532 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
534 if (DataRange
->FormatSize
== sizeof(KSDATARANGE_AUDIO
))
536 DataRangeAudio
= (PKSDATARANGE_AUDIO
)DataRange
;
538 if (IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
539 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
540 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
542 DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio
->MinimumSampleFrequency
, DataRangeAudio
->MaximumSampleFrequency
,
543 DataRangeAudio
->MinimumBitsPerSample
, DataRangeAudio
->MaximumBitsPerSample
, DataRangeAudio
->MaximumChannels
);
545 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 11025, WAVE_FORMAT_1M08
, WAVE_FORMAT_1S08
, WAVE_FORMAT_1M16
, WAVE_FORMAT_1S16
);
546 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 22050, WAVE_FORMAT_2M08
, WAVE_FORMAT_2S08
, WAVE_FORMAT_2M16
, WAVE_FORMAT_2S16
);
547 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 44100, WAVE_FORMAT_4M08
, WAVE_FORMAT_4S08
, WAVE_FORMAT_4M16
, WAVE_FORMAT_4S16
);
548 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 48000, WAVE_FORMAT_48M08
, WAVE_FORMAT_48S08
, WAVE_FORMAT_48M16
, WAVE_FORMAT_48S16
);
549 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 96000, WAVE_FORMAT_96M08
, WAVE_FORMAT_96S08
, WAVE_FORMAT_96M16
, WAVE_FORMAT_96S16
);
552 wChannels
= DataRangeAudio
->MaximumChannels
;
553 dwSupport
= WAVECAPS_VOLUME
; //FIXME get info from nodes
557 DataRange
= (PKSDATARANGE
)((PUCHAR
)DataRange
+ DataRange
->FormatSize
);
560 DeviceInfo
->u
.WaveOutCaps
.dwFormats
= dwFormats
;
561 DeviceInfo
->u
.WaveOutCaps
.dwSupport
= dwSupport
;
562 DeviceInfo
->u
.WaveOutCaps
.wChannels
= wChannels
;
563 DeviceInfo
->u
.WaveOutCaps
.szPname
[0] = L
'\0';
566 ExFreePool(MultipleItem
);
567 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
573 IN PDEVICE_OBJECT DeviceObject
,
575 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
576 IN PWDMAUD_CLIENT ClientInfo
)
580 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
582 if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
584 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
585 ZwClose(DeviceInfo
->hDevice
);
586 ClientInfo
->hPins
[Index
].Handle
= NULL
;
587 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
588 return STATUS_SUCCESS
;
591 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
592 return STATUS_INVALID_PARAMETER
;
598 IN PDEVICE_OBJECT DeviceObject
,
601 PIO_STACK_LOCATION IoStack
;
602 PWDMAUD_DEVICE_INFO DeviceInfo
;
603 PWDMAUD_CLIENT ClientInfo
;
605 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
607 DPRINT("WdmAudDeviceControl entered\n");
609 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
611 /* invalid parameter */
612 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
613 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
616 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
618 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
620 /* invalid parameter */
621 DPRINT1("Error: device type not set\n");
622 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
625 if (!IoStack
->FileObject
)
627 /* file object parameter */
628 DPRINT1("Error: file object is not attached\n");
629 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
631 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
633 DPRINT("WdmAudDeviceControl entered\n");
635 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
637 case IOCTL_OPEN_WDMAUD
:
638 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
639 case IOCTL_GETNUMDEVS_TYPE
:
640 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
641 case IOCTL_SETDEVICE_STATE
:
642 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
643 case IOCTL_GETCAPABILITIES
:
644 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
645 case IOCTL_CLOSE_WDMAUD
:
646 return WdmAudIoctlClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
648 DPRINT1("IOCTL_GETPOS\n");
650 case IOCTL_GETVOLUME
:
651 case IOCTL_SETVOLUME
:
653 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
657 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
663 IN PDEVICE_OBJECT DeviceObject
,
666 PIO_STACK_LOCATION IoStack
;
667 PWDMAUD_DEVICE_INFO DeviceInfo
;
668 PWDMAUD_CLIENT ClientInfo
;
669 NTSTATUS Status
= STATUS_SUCCESS
;
671 PCONTEXT_WRITE Packet
;
672 PFILE_OBJECT FileObject
;
673 IO_STATUS_BLOCK IoStatusBlock
;
677 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
679 //DPRINT("WdmAudWrite entered\n");
681 if (IoStack
->Parameters
.Write
.Length
< sizeof(WDMAUD_DEVICE_INFO
))
683 /* invalid parameter */
684 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.Write
.Length
, sizeof(WDMAUD_DEVICE_INFO
));
685 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
688 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)MmGetMdlVirtualAddress(Irp
->MdlAddress
);
691 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
692 if (!NT_SUCCESS(Status
))
694 DPRINT1("Invalid buffer handle %x\n", DeviceInfo
->hDevice
);
695 return SetIrpIoStatus(Irp
, Status
, 0);
699 //DPRINT("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa);
700 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
702 /* invalid parameter */
703 DPRINT1("Error: device type not set\n");
704 ObDereferenceObject(FileObject
);
705 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
708 if (!IoStack
->FileObject
)
710 /* file object parameter */
711 DPRINT1("Error: file object is not attached\n");
712 ObDereferenceObject(FileObject
);
713 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
715 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
718 /* setup stream context */
719 Packet
= (PCONTEXT_WRITE
)ExAllocatePool(NonPagedPool
, sizeof(CONTEXT_WRITE
));
723 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
726 Packet
->Header
.FrameExtent
= DeviceInfo
->BufferSize
;
727 Packet
->Header
.DataUsed
= DeviceInfo
->BufferSize
;
728 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
729 Packet
->Header
.PresentationTime
.Numerator
= 1;
730 Packet
->Header
.PresentationTime
.Denominator
= 1;
733 Buffer
= ExAllocatePool(NonPagedPool
, DeviceInfo
->BufferSize
);
738 ObDereferenceObject(FileObject
);
739 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
741 Packet
->Header
.Data
= Buffer
;
743 Mdl
= IoAllocateMdl(DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
, FALSE
, FALSE
, FALSE
);
748 ObDereferenceObject(FileObject
);
750 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
755 MmProbeAndLockPages(Mdl
, UserMode
, IoReadAccess
);
757 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
759 /* Exception, get the error code */
760 Status
= _SEH2_GetExceptionCode();
764 if (!NT_SUCCESS(Status
))
766 DPRINT1("Invalid buffer supplied\n");
770 ObDereferenceObject(FileObject
);
771 return SetIrpIoStatus(Irp
, Status
, 0);
774 SystemBuffer
= MmGetSystemAddressForMdlSafe(Mdl
, NormalPagePriority
);
777 DPRINT1("Invalid buffer supplied\n");
781 ObDereferenceObject(FileObject
);
782 return SetIrpIoStatus(Irp
, Status
, 0);
785 RtlMoveMemory(Buffer
, SystemBuffer
, DeviceInfo
->BufferSize
);
789 KsStreamIo(FileObject
, NULL
, NULL
, NULL
, NULL
, 0, &IoStatusBlock
, Packet
, sizeof(CONTEXT_WRITE
), KSSTREAM_WRITE
, KernelMode
);
790 ObDereferenceObject(FileObject
);
791 return IoStatusBlock
.Status
;