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}};
27 Irp
->IoStatus
.Information
= Length
;
28 Irp
->IoStatus
.Status
= Status
;
29 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
36 IN PDEVICE_OBJECT DeviceObject
,
37 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
38 IN PWDMAUD_CLIENT ClientInfo
,
43 ULONG Count
, BytesReturned
, Index
, SubIndex
, Result
, NumPins
;
45 KSPIN_COMMUNICATION Communication
;
46 KSPIN_DATAFLOW DataFlow
;
48 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
50 DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo
->DeviceType
);
51 return STATUS_UNSUCCESSFUL
;
54 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
55 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
56 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
58 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
59 if (!NT_SUCCESS(Status
))
60 return STATUS_UNSUCCESSFUL
;
63 for(Index
= 0; Index
< Count
; Index
++)
65 /* query number of pins */
66 Pin
.Reserved
= Index
; // see sysaudio
67 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
68 Pin
.Property
.Set
= KSPROPSETID_Pin
;
69 Pin
.Property
.Id
= KSPROPERTY_PIN_CTYPES
;
72 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&NumPins
, sizeof(ULONG
), &BytesReturned
);
73 if (NT_SUCCESS(Status
))
75 /* enumerate now all pins */
76 for(SubIndex
= 0; SubIndex
< NumPins
; SubIndex
++)
79 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
80 Communication
= KSPIN_COMMUNICATION_NONE
;
82 /* get pin communication type */
83 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
85 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
88 /* get pin dataflow type */
89 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
91 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
93 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_IN
)
95 if(DeviceInfo
->DeviceIndex
== Result
)
100 return STATUS_SUCCESS
;
106 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
108 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_OUT
)
110 if(DeviceInfo
->DeviceIndex
== Result
)
112 /* found the index */
115 return STATUS_SUCCESS
;
124 return STATUS_UNSUCCESSFUL
;
129 IN PDEVICE_OBJECT DeviceObject
,
131 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
132 IN PWDMAUD_CLIENT ClientInfo
)
134 PSYSAUDIO_INSTANCE_INFO InstanceInfo
;
137 ACCESS_MASK DesiredAccess
= 0;
139 KSPIN_CONNECT
* PinConnect
;
141 KSDATAFORMAT_WAVEFORMATEX
* DataFormat
;
145 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
147 DPRINT1("FIXME: only waveout devices are supported\n");
148 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
151 Status
= GetFilterIdAndPinId(DeviceObject
, DeviceInfo
, ClientInfo
, &FilterId
, &PinId
);
152 if (!NT_SUCCESS(Status
))
154 DPRINT1("Invalid device index %u\n", DeviceInfo
->DeviceIndex
);
155 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
159 Length
= sizeof(KSDATAFORMAT_WAVEFORMATEX
) + sizeof(KSPIN_CONNECT
) + sizeof(SYSAUDIO_INSTANCE_INFO
);
160 InstanceInfo
= ExAllocatePool(NonPagedPool
, Length
);
164 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
167 InstanceInfo
->Property
.Set
= KSPROPSETID_Sysaudio
;
168 InstanceInfo
->Property
.Id
= KSPROPERTY_SYSAUDIO_INSTANCE_INFO
;
169 InstanceInfo
->Property
.Flags
= KSPROPERTY_TYPE_SET
;
170 InstanceInfo
->Flags
= 0;
171 InstanceInfo
->DeviceNumber
= FilterId
;
173 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, sizeof(SYSAUDIO_INSTANCE_INFO
), NULL
, 0, &BytesReturned
);
175 if (!NT_SUCCESS(Status
))
177 /* failed to acquire audio device */
178 DPRINT1("KsSynchronousIoControlDevice failed with %x\n", Status
);
179 ExFreePool(InstanceInfo
);
180 return SetIrpIoStatus(Irp
, Status
, 0);
183 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
||
184 DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
||
185 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
187 DesiredAccess
|= GENERIC_READ
;
190 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
||
191 DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
||
192 DeviceInfo
->DeviceType
== AUX_DEVICE_TYPE
||
193 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
195 DesiredAccess
|= GENERIC_WRITE
;
198 PinConnect
= (KSPIN_CONNECT
*)(InstanceInfo
+ 1);
201 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
202 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
203 PinConnect
->Interface
.Flags
= 0;
204 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
205 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
206 PinConnect
->Medium
.Flags
= 0;
207 PinConnect
->PinId
= PinId
;
208 PinConnect
->PinToHandle
= ClientInfo
->hSysAudio
;
209 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
210 PinConnect
->Priority
.PrioritySubClass
= 1;
213 DataFormat
= (KSDATAFORMAT_WAVEFORMATEX
*) (PinConnect
+ 1);
214 DataFormat
->WaveFormatEx
.wFormatTag
= DeviceInfo
->u
.WaveFormatEx
.wFormatTag
;
215 DataFormat
->WaveFormatEx
.nChannels
= DeviceInfo
->u
.WaveFormatEx
.nChannels
;
216 DataFormat
->WaveFormatEx
.nSamplesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nSamplesPerSec
;
217 DataFormat
->WaveFormatEx
.nBlockAlign
= DeviceInfo
->u
.WaveFormatEx
.nBlockAlign
;
218 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nAvgBytesPerSec
;
219 DataFormat
->WaveFormatEx
.wBitsPerSample
= DeviceInfo
->u
.WaveFormatEx
.wBitsPerSample
;
220 DataFormat
->WaveFormatEx
.cbSize
= 0;
221 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
222 DataFormat
->DataFormat
.Flags
= 0;
223 DataFormat
->DataFormat
.Reserved
= 0;
224 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
226 if (DeviceInfo
->u
.WaveFormatEx
.wFormatTag
!= WAVE_FORMAT_PCM
)
229 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
230 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
231 DataFormat
->DataFormat
.SampleSize
= 4;
233 /* ros specific pin creation request */
234 InstanceInfo
->Property
.Id
= (ULONG
)-1;
235 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, Length
, &PinHandle
, sizeof(HANDLE
), &BytesReturned
);
236 if (NT_SUCCESS(Status
))
238 PHANDLE Handels
= ExAllocatePool(NonPagedPool
, sizeof(HANDLE
) * (ClientInfo
->NumPins
+1));
242 if (ClientInfo
->NumPins
)
244 RtlMoveMemory(Handels
, ClientInfo
->hPins
, sizeof(HANDLE
) * ClientInfo
->NumPins
);
245 ExFreePool(ClientInfo
->hPins
);
248 ClientInfo
->hPins
= Handels
;
249 ClientInfo
->hPins
[ClientInfo
->NumPins
] = PinHandle
;
250 ClientInfo
->NumPins
++;
252 DeviceInfo
->hDevice
= PinHandle
;
256 DeviceInfo
->hDevice
= NULL
;
259 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
263 WdmAudControlDeviceType(
264 IN PDEVICE_OBJECT DeviceObject
,
266 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
267 IN PWDMAUD_CLIENT ClientInfo
)
270 ULONG Count
, BytesReturned
, Index
, SubIndex
, Result
, NumPins
;
272 KSPIN_COMMUNICATION Communication
;
273 KSPIN_DATAFLOW DataFlow
;
275 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
277 DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo
->DeviceType
);
278 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
281 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
282 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
283 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
285 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
286 if (!NT_SUCCESS(Status
))
288 DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status
);
289 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
292 /* now enumerate all available filters */
293 for(Index
= 0; Index
< Count
; Index
++)
295 /* query number of pins */
296 Pin
.Reserved
= Index
; // see sysaudio
297 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
298 Pin
.Property
.Set
= KSPROPSETID_Pin
;
299 Pin
.Property
.Id
= KSPROPERTY_PIN_CTYPES
;
302 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&NumPins
, sizeof(ULONG
), &BytesReturned
);
303 if (NT_SUCCESS(Status
))
305 /* enumerate now all pins */
306 for(SubIndex
= 0; SubIndex
< NumPins
; SubIndex
++)
308 Pin
.PinId
= SubIndex
;
309 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
310 Communication
= KSPIN_COMMUNICATION_NONE
;
312 /* get pin communication type */
313 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
315 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
318 /* get pin dataflow type */
319 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
321 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
323 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_IN
)
326 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
328 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_OUT
)
334 DPRINT1("KSPROPERTY_PIN_CTYPES index %u failed with %x\n", Index
, Status
);
338 if (NT_SUCCESS(Status
))
339 DeviceInfo
->DeviceCount
= Result
;
341 DeviceInfo
->DeviceCount
= 0;
343 DPRINT1("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
344 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
348 WdmAudControlDeviceState(
349 IN PDEVICE_OBJECT DeviceObject
,
351 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
352 IN PWDMAUD_CLIENT ClientInfo
)
358 PFILE_OBJECT FileObject
;
360 DPRINT1("WdmAudControlDeviceState\n");
362 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
363 if (!NT_SUCCESS(Status
))
365 DPRINT1("Error: invalid device handle provided %p\n", DeviceInfo
->hDevice
);
366 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
369 Property
.Set
= KSPROPSETID_Connection
;
370 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
371 Property
.Flags
= KSPROPERTY_TYPE_SET
;
373 State
= DeviceInfo
->State
;
375 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
377 ObDereferenceObject(FileObject
);
379 DPRINT1("WdmAudControlDeviceState Status %x\n", Status
);
380 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
385 WdmAudWriteCompleted(
386 IN PDEVICE_OBJECT DeviceObject
,
390 PWRITE_CONTEXT Context
= (PWRITE_CONTEXT
)Ctx
;
392 Context
->Irp
->IoStatus
.Information
= Context
->Length
;
393 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
394 IoCompleteRequest(Context
->Irp
, IO_SOUND_INCREMENT
);
397 return STATUS_SUCCESS
;
402 IN PKSDATARANGE_AUDIO DataRangeAudio
,
403 ULONG SampleFrequency
,
411 if (DataRangeAudio
->MinimumSampleFrequency
<= SampleFrequency
&& DataRangeAudio
->MaximumSampleFrequency
>= SampleFrequency
)
413 if (DataRangeAudio
->MinimumBitsPerSample
<= 8 && DataRangeAudio
->MaximumBitsPerSample
>= 8)
416 if (DataRangeAudio
->MaximumChannels
>= 2)
418 Result
|= Stereo8Bit
;
422 if (DataRangeAudio
->MinimumBitsPerSample
<= 16 && DataRangeAudio
->MaximumBitsPerSample
>= 16)
425 if (DataRangeAudio
->MaximumChannels
>= 2)
427 Result
|= Stereo8Bit
;
437 IN PDEVICE_OBJECT DeviceObject
,
439 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
440 IN PWDMAUD_CLIENT ClientInfo
)
442 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
444 KSCOMPONENTID ComponentId
;
445 KSMULTIPLE_ITEM
* MultipleItem
;
447 PKSDATARANGE_AUDIO DataRangeAudio
;
448 PKSDATARANGE DataRange
;
456 DPRINT("WdmAudCapabilities entered\n");
459 Status
= GetFilterIdAndPinId(DeviceObject
, DeviceInfo
, ClientInfo
, &FilterId
, &PinId
);
460 if (!NT_SUCCESS(Status
))
462 DPRINT1("Invalid device index provided %u\n", DeviceInfo
->DeviceIndex
);
463 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
466 PinProperty
.PinId
= FilterId
;
467 PinProperty
.Property
.Set
= KSPROPSETID_Sysaudio
;
468 PinProperty
.Property
.Id
= KSPROPERTY_SYSAUDIO_COMPONENT_ID
;
469 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
471 RtlZeroMemory(&ComponentId
, sizeof(KSCOMPONENTID
));
473 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)&ComponentId
, sizeof(KSCOMPONENTID
), &BytesReturned
);
474 if (NT_SUCCESS(Status
))
476 DeviceInfo
->u
.WaveOutCaps
.wMid
= ComponentId
.Manufacturer
.Data1
- 0xd5a47fa7;
477 DeviceInfo
->u
.WaveOutCaps
.vDriverVersion
= MAKELONG(ComponentId
.Version
, ComponentId
.Revision
);
480 PinProperty
.Reserved
= DeviceInfo
->DeviceIndex
;
481 PinProperty
.PinId
= PinId
;
482 PinProperty
.Property
.Set
= KSPROPSETID_Pin
;
483 PinProperty
.Property
.Id
= KSPROPERTY_PIN_DATARANGES
;
484 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
487 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)NULL
, 0, &BytesReturned
);
488 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
490 return SetIrpIoStatus(Irp
, Status
, 0);
493 MultipleItem
= ExAllocatePool(NonPagedPool
, BytesReturned
);
497 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
500 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
501 if (!NT_SUCCESS(Status
))
503 ExFreePool(MultipleItem
);
504 return SetIrpIoStatus(Irp
, Status
, 0);
507 DataRange
= (PKSDATARANGE
) (MultipleItem
+ 1);
508 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
510 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
512 if (DataRange
->FormatSize
== sizeof(KSDATARANGE_AUDIO
))
514 DataRangeAudio
= (PKSDATARANGE_AUDIO
)DataRange
;
516 if (IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
517 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
518 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
520 DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio
->MinimumSampleFrequency
, DataRangeAudio
->MaximumSampleFrequency
,
521 DataRangeAudio
->MinimumBitsPerSample
, DataRangeAudio
->MaximumBitsPerSample
, DataRangeAudio
->MaximumChannels
);
523 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 11025, WAVE_FORMAT_1M08
, WAVE_FORMAT_1S08
, WAVE_FORMAT_1M16
, WAVE_FORMAT_1S16
);
524 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 22050, WAVE_FORMAT_2M08
, WAVE_FORMAT_2S08
, WAVE_FORMAT_2M16
, WAVE_FORMAT_2S16
);
525 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 44100, WAVE_FORMAT_4M08
, WAVE_FORMAT_4S08
, WAVE_FORMAT_4M16
, WAVE_FORMAT_4S16
);
526 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 48000, WAVE_FORMAT_48M08
, WAVE_FORMAT_48S08
, WAVE_FORMAT_48M16
, WAVE_FORMAT_48S16
);
527 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 96000, WAVE_FORMAT_96M08
, WAVE_FORMAT_96S08
, WAVE_FORMAT_96M16
, WAVE_FORMAT_96S16
);
530 wChannels
= DataRangeAudio
->MaximumChannels
;
531 dwSupport
= WAVECAPS_VOLUME
; //FIXME get info from nodes
535 DataRange
= (PKSDATARANGE
)((PUCHAR
)DataRange
+ DataRange
->FormatSize
);
538 DeviceInfo
->u
.WaveOutCaps
.dwFormats
= dwFormats
;
539 DeviceInfo
->u
.WaveOutCaps
.dwSupport
= dwSupport
;
540 DeviceInfo
->u
.WaveOutCaps
.wChannels
= wChannels
;
541 DeviceInfo
->u
.WaveOutCaps
.szPname
[0] = L
'\0';
544 ExFreePool(MultipleItem
);
545 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
551 IN PDEVICE_OBJECT DeviceObject
,
553 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
554 IN PWDMAUD_CLIENT ClientInfo
)
558 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
560 if (ClientInfo
->hPins
[Index
] == DeviceInfo
->hDevice
)
562 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
563 ZwClose(DeviceInfo
->hDevice
);
564 ClientInfo
->hPins
[Index
] = NULL
;
565 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
566 return STATUS_SUCCESS
;
569 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
570 return STATUS_INVALID_PARAMETER
;
576 IN PDEVICE_OBJECT DeviceObject
,
579 PIO_STACK_LOCATION IoStack
;
580 PWDMAUD_DEVICE_INFO DeviceInfo
;
581 PWDMAUD_CLIENT ClientInfo
;
583 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
585 DPRINT1("WdmAudDeviceControl entered\n");
587 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
589 /* invalid parameter */
590 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
591 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
594 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
596 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
598 /* invalid parameter */
599 DPRINT1("Error: device type not set\n");
600 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
603 if (!IoStack
->FileObject
)
605 /* file object parameter */
606 DPRINT1("Error: file object is not attached\n");
607 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
609 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
611 DPRINT1("WdmAudDeviceControl entered\n");
613 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
615 case IOCTL_OPEN_WDMAUD
:
616 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
617 case IOCTL_GETNUMDEVS_TYPE
:
618 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
619 case IOCTL_SETDEVICE_STATE
:
620 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
621 case IOCTL_GETCAPABILITIES
:
622 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
623 case IOCTL_CLOSE_WDMAUD
:
624 return WdmAudClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
626 case IOCTL_GETVOLUME
:
627 case IOCTL_SETVOLUME
:
629 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
633 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
639 IN PDEVICE_OBJECT DeviceObject
,
642 PIO_STACK_LOCATION IoStack
;
643 PWDMAUD_DEVICE_INFO DeviceInfo
;
644 PWDMAUD_CLIENT ClientInfo
;
645 NTSTATUS Status
= STATUS_SUCCESS
;
647 PCONTEXT_WRITE Packet
;
648 PFILE_OBJECT FileObject
;
649 IO_STATUS_BLOCK IoStatusBlock
;
651 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
653 //DPRINT("WdmAudWrite entered\n");
655 if (IoStack
->Parameters
.Write
.Length
< sizeof(WDMAUD_DEVICE_INFO
))
657 /* invalid parameter */
658 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.Write
.Length
, sizeof(WDMAUD_DEVICE_INFO
));
659 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
662 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)MmGetMdlVirtualAddress(Irp
->MdlAddress
);
665 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
666 if (!NT_SUCCESS(Status
))
668 DPRINT1("Invalid buffer handle %x\n", DeviceInfo
->hDevice
);
669 return SetIrpIoStatus(Irp
, Status
, 0);
673 //DPRINT("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa);
674 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
676 /* invalid parameter */
677 DPRINT1("Error: device type not set\n");
678 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
681 if (!IoStack
->FileObject
)
683 /* file object parameter */
684 DPRINT1("Error: file object is not attached\n");
685 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
687 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
690 /* setup stream context */
691 Packet
= (PCONTEXT_WRITE
)ExAllocatePool(NonPagedPool
, sizeof(CONTEXT_WRITE
));
695 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
698 Packet
->Header
.FrameExtent
= DeviceInfo
->BufferSize
;
699 Packet
->Header
.DataUsed
= DeviceInfo
->BufferSize
;
700 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
701 Packet
->Header
.PresentationTime
.Numerator
= 1;
702 Packet
->Header
.PresentationTime
.Denominator
= 1;
705 Buffer
= ExAllocatePool(NonPagedPool
, DeviceInfo
->BufferSize
);
710 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
712 Packet
->Header
.Data
= Buffer
;
716 ProbeForRead(DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
, TYPE_ALIGNMENT(char));
717 RtlMoveMemory(Buffer
, DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
);
719 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 /* Exception, get the error code */
722 Status
= _SEH2_GetExceptionCode();
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("Invalid buffer supplied\n");
731 return SetIrpIoStatus(Irp
, Status
, 0);
734 KsStreamIo(FileObject
, NULL
, NULL
, NULL
, NULL
, 0, &IoStatusBlock
, Packet
, sizeof(CONTEXT_WRITE
), KSSTREAM_WRITE
, KernelMode
);
737 return IoStatusBlock
.Status
;