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 / wavein 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);
158 Length
= sizeof(KSDATAFORMAT_WAVEFORMATEX
) + sizeof(KSPIN_CONNECT
) + sizeof(SYSAUDIO_INSTANCE_INFO
);
159 InstanceInfo
= ExAllocatePool(NonPagedPool
, Length
);
163 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
166 InstanceInfo
->Property
.Set
= KSPROPSETID_Sysaudio
;
167 InstanceInfo
->Property
.Id
= KSPROPERTY_SYSAUDIO_INSTANCE_INFO
;
168 InstanceInfo
->Property
.Flags
= KSPROPERTY_TYPE_SET
;
169 InstanceInfo
->Flags
= 0;
170 InstanceInfo
->DeviceNumber
= FilterId
;
172 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, sizeof(SYSAUDIO_INSTANCE_INFO
), NULL
, 0, &BytesReturned
);
174 if (!NT_SUCCESS(Status
))
176 /* failed to acquire audio device */
177 DPRINT1("KsSynchronousIoControlDevice failed with %x\n", Status
);
178 ExFreePool(InstanceInfo
);
179 return SetIrpIoStatus(Irp
, Status
, 0);
182 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
||
183 DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
||
184 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
186 DesiredAccess
|= GENERIC_READ
;
189 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
||
190 DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
||
191 DeviceInfo
->DeviceType
== AUX_DEVICE_TYPE
||
192 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
194 DesiredAccess
|= GENERIC_WRITE
;
197 PinConnect
= (KSPIN_CONNECT
*)(InstanceInfo
+ 1);
200 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
201 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
202 PinConnect
->Interface
.Flags
= 0;
203 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
204 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
205 PinConnect
->Medium
.Flags
= 0;
206 PinConnect
->PinId
= PinId
;
207 PinConnect
->PinToHandle
= ClientInfo
->hSysAudio
;
208 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
209 PinConnect
->Priority
.PrioritySubClass
= 1;
212 DataFormat
= (KSDATAFORMAT_WAVEFORMATEX
*) (PinConnect
+ 1);
213 DataFormat
->WaveFormatEx
.wFormatTag
= DeviceInfo
->u
.WaveFormatEx
.wFormatTag
;
214 DataFormat
->WaveFormatEx
.nChannels
= DeviceInfo
->u
.WaveFormatEx
.nChannels
;
215 DataFormat
->WaveFormatEx
.nSamplesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nSamplesPerSec
;
216 DataFormat
->WaveFormatEx
.nBlockAlign
= DeviceInfo
->u
.WaveFormatEx
.nBlockAlign
;
217 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nAvgBytesPerSec
;
218 DataFormat
->WaveFormatEx
.wBitsPerSample
= DeviceInfo
->u
.WaveFormatEx
.wBitsPerSample
;
219 DataFormat
->WaveFormatEx
.cbSize
= 0;
220 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
221 DataFormat
->DataFormat
.Flags
= 0;
222 DataFormat
->DataFormat
.Reserved
= 0;
223 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
225 if (DeviceInfo
->u
.WaveFormatEx
.wFormatTag
!= WAVE_FORMAT_PCM
)
228 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
229 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
230 DataFormat
->DataFormat
.SampleSize
= 4;
232 /* ros specific pin creation request */
233 InstanceInfo
->Property
.Id
= (ULONG
)-1;
234 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, Length
, &PinHandle
, sizeof(HANDLE
), &BytesReturned
);
235 if (NT_SUCCESS(Status
))
239 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
241 if (ClientInfo
->hPins
[Index
] == PinHandle
)
243 /* the pin handle has been re-used */
244 DeviceInfo
->hDevice
= PinHandle
;
245 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
250 Handels
= ExAllocatePool(NonPagedPool
, sizeof(HANDLE
) * (ClientInfo
->NumPins
+1));
254 if (ClientInfo
->NumPins
)
256 RtlMoveMemory(Handels
, ClientInfo
->hPins
, sizeof(HANDLE
) * ClientInfo
->NumPins
);
257 ExFreePool(ClientInfo
->hPins
);
260 ClientInfo
->hPins
= Handels
;
261 ClientInfo
->hPins
[ClientInfo
->NumPins
] = PinHandle
;
262 ClientInfo
->NumPins
++;
264 DeviceInfo
->hDevice
= PinHandle
;
268 DeviceInfo
->hDevice
= NULL
;
271 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
275 WdmAudControlDeviceType(
276 IN PDEVICE_OBJECT DeviceObject
,
278 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
279 IN PWDMAUD_CLIENT ClientInfo
)
282 ULONG Count
, BytesReturned
, Index
, SubIndex
, Result
, NumPins
;
284 KSPIN_COMMUNICATION Communication
;
285 KSPIN_DATAFLOW DataFlow
;
287 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
&& DeviceInfo
->DeviceType
!= WAVE_IN_DEVICE_TYPE
)
289 DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo
->DeviceType
);
290 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
293 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
294 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
295 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
297 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
298 if (!NT_SUCCESS(Status
))
300 DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status
);
301 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
304 /* now enumerate all available filters */
305 for(Index
= 0; Index
< Count
; Index
++)
307 /* query number of pins */
308 Pin
.Reserved
= Index
; // see sysaudio
309 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
310 Pin
.Property
.Set
= KSPROPSETID_Pin
;
311 Pin
.Property
.Id
= KSPROPERTY_PIN_CTYPES
;
314 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&NumPins
, sizeof(ULONG
), &BytesReturned
);
315 if (NT_SUCCESS(Status
))
317 /* enumerate now all pins */
318 for(SubIndex
= 0; SubIndex
< NumPins
; SubIndex
++)
320 Pin
.PinId
= SubIndex
;
321 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
322 Communication
= KSPIN_COMMUNICATION_NONE
;
324 /* get pin communication type */
325 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
327 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
330 /* get pin dataflow type */
331 KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)&DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
333 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
335 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_IN
)
338 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
340 if (Communication
== KSPIN_COMMUNICATION_SINK
&& DataFlow
== KSPIN_DATAFLOW_OUT
)
348 if (NT_SUCCESS(Status
))
349 DeviceInfo
->DeviceCount
= Result
;
351 DeviceInfo
->DeviceCount
= 0;
353 DPRINT1("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
354 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
358 WdmAudControlDeviceState(
359 IN PDEVICE_OBJECT DeviceObject
,
361 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
362 IN PWDMAUD_CLIENT ClientInfo
)
368 PFILE_OBJECT FileObject
;
370 //DPRINT1("WdmAudControlDeviceState\n");
372 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
373 if (!NT_SUCCESS(Status
))
375 DPRINT1("Error: invalid device handle provided %p\n", DeviceInfo
->hDevice
);
376 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
379 Property
.Set
= KSPROPSETID_Connection
;
380 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
381 Property
.Flags
= KSPROPERTY_TYPE_SET
;
383 State
= DeviceInfo
->State
;
385 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
387 ObDereferenceObject(FileObject
);
389 //DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
390 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
395 IN PKSDATARANGE_AUDIO DataRangeAudio
,
396 ULONG SampleFrequency
,
404 if (DataRangeAudio
->MinimumSampleFrequency
<= SampleFrequency
&& DataRangeAudio
->MaximumSampleFrequency
>= SampleFrequency
)
406 if (DataRangeAudio
->MinimumBitsPerSample
<= 8 && DataRangeAudio
->MaximumBitsPerSample
>= 8)
409 if (DataRangeAudio
->MaximumChannels
>= 2)
411 Result
|= Stereo8Bit
;
415 if (DataRangeAudio
->MinimumBitsPerSample
<= 16 && DataRangeAudio
->MaximumBitsPerSample
>= 16)
418 if (DataRangeAudio
->MaximumChannels
>= 2)
420 Result
|= Stereo8Bit
;
430 IN PDEVICE_OBJECT DeviceObject
,
432 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
433 IN PWDMAUD_CLIENT ClientInfo
)
435 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
437 KSCOMPONENTID ComponentId
;
438 KSMULTIPLE_ITEM
* MultipleItem
;
440 PKSDATARANGE_AUDIO DataRangeAudio
;
441 PKSDATARANGE DataRange
;
449 DPRINT("WdmAudCapabilities entered\n");
451 Status
= GetFilterIdAndPinId(DeviceObject
, DeviceInfo
, ClientInfo
, &FilterId
, &PinId
);
452 if (!NT_SUCCESS(Status
))
454 DPRINT1("Invalid device index provided %u\n", DeviceInfo
->DeviceIndex
);
455 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
458 PinProperty
.PinId
= FilterId
;
459 PinProperty
.Property
.Set
= KSPROPSETID_Sysaudio
;
460 PinProperty
.Property
.Id
= KSPROPERTY_SYSAUDIO_COMPONENT_ID
;
461 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
463 RtlZeroMemory(&ComponentId
, sizeof(KSCOMPONENTID
));
465 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)&ComponentId
, sizeof(KSCOMPONENTID
), &BytesReturned
);
466 if (NT_SUCCESS(Status
))
468 DeviceInfo
->u
.WaveOutCaps
.wMid
= ComponentId
.Manufacturer
.Data1
- 0xd5a47fa7;
469 DeviceInfo
->u
.WaveOutCaps
.vDriverVersion
= MAKELONG(ComponentId
.Version
, ComponentId
.Revision
);
472 PinProperty
.Reserved
= DeviceInfo
->DeviceIndex
;
473 PinProperty
.PinId
= PinId
;
474 PinProperty
.Property
.Set
= KSPROPSETID_Pin
;
475 PinProperty
.Property
.Id
= KSPROPERTY_PIN_DATARANGES
;
476 PinProperty
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
479 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)NULL
, 0, &BytesReturned
);
480 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
482 return SetIrpIoStatus(Irp
, Status
, 0);
485 MultipleItem
= ExAllocatePool(NonPagedPool
, BytesReturned
);
489 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
492 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&PinProperty
, sizeof(KSP_PIN
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
493 if (!NT_SUCCESS(Status
))
495 ExFreePool(MultipleItem
);
496 return SetIrpIoStatus(Irp
, Status
, 0);
499 DataRange
= (PKSDATARANGE
) (MultipleItem
+ 1);
500 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
502 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
504 if (DataRange
->FormatSize
== sizeof(KSDATARANGE_AUDIO
))
506 DataRangeAudio
= (PKSDATARANGE_AUDIO
)DataRange
;
508 if (IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
509 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
510 IsEqualGUIDAligned(&DataRangeAudio
->DataRange
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
512 DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio
->MinimumSampleFrequency
, DataRangeAudio
->MaximumSampleFrequency
,
513 DataRangeAudio
->MinimumBitsPerSample
, DataRangeAudio
->MaximumBitsPerSample
, DataRangeAudio
->MaximumChannels
);
515 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 11025, WAVE_FORMAT_1M08
, WAVE_FORMAT_1S08
, WAVE_FORMAT_1M16
, WAVE_FORMAT_1S16
);
516 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 22050, WAVE_FORMAT_2M08
, WAVE_FORMAT_2S08
, WAVE_FORMAT_2M16
, WAVE_FORMAT_2S16
);
517 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 44100, WAVE_FORMAT_4M08
, WAVE_FORMAT_4S08
, WAVE_FORMAT_4M16
, WAVE_FORMAT_4S16
);
518 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 48000, WAVE_FORMAT_48M08
, WAVE_FORMAT_48S08
, WAVE_FORMAT_48M16
, WAVE_FORMAT_48S16
);
519 dwFormats
|= CheckFormatSupport(DataRangeAudio
, 96000, WAVE_FORMAT_96M08
, WAVE_FORMAT_96S08
, WAVE_FORMAT_96M16
, WAVE_FORMAT_96S16
);
522 wChannels
= DataRangeAudio
->MaximumChannels
;
523 dwSupport
= WAVECAPS_VOLUME
; //FIXME get info from nodes
527 DataRange
= (PKSDATARANGE
)((PUCHAR
)DataRange
+ DataRange
->FormatSize
);
530 DeviceInfo
->u
.WaveOutCaps
.dwFormats
= dwFormats
;
531 DeviceInfo
->u
.WaveOutCaps
.dwSupport
= dwSupport
;
532 DeviceInfo
->u
.WaveOutCaps
.wChannels
= wChannels
;
533 DeviceInfo
->u
.WaveOutCaps
.szPname
[0] = L
'\0';
536 ExFreePool(MultipleItem
);
537 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
543 IN PDEVICE_OBJECT DeviceObject
,
545 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
546 IN PWDMAUD_CLIENT ClientInfo
)
550 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
552 if (ClientInfo
->hPins
[Index
] == DeviceInfo
->hDevice
)
554 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
555 ZwClose(DeviceInfo
->hDevice
);
556 ClientInfo
->hPins
[Index
] = NULL
;
557 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
558 return STATUS_SUCCESS
;
561 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
562 return STATUS_INVALID_PARAMETER
;
568 IN PDEVICE_OBJECT DeviceObject
,
571 PIO_STACK_LOCATION IoStack
;
572 PWDMAUD_DEVICE_INFO DeviceInfo
;
573 PWDMAUD_CLIENT ClientInfo
;
575 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
577 DPRINT("WdmAudDeviceControl entered\n");
579 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
581 /* invalid parameter */
582 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
583 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
586 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
588 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
590 /* invalid parameter */
591 DPRINT1("Error: device type not set\n");
592 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
595 if (!IoStack
->FileObject
)
597 /* file object parameter */
598 DPRINT1("Error: file object is not attached\n");
599 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
601 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
603 DPRINT("WdmAudDeviceControl entered\n");
605 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
607 case IOCTL_OPEN_WDMAUD
:
608 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
609 case IOCTL_GETNUMDEVS_TYPE
:
610 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
611 case IOCTL_SETDEVICE_STATE
:
612 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
613 case IOCTL_GETCAPABILITIES
:
614 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
615 case IOCTL_CLOSE_WDMAUD
:
616 return WdmAudIoctlClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
618 case IOCTL_GETVOLUME
:
619 case IOCTL_SETVOLUME
:
621 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
625 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
631 IN PDEVICE_OBJECT DeviceObject
,
634 PIO_STACK_LOCATION IoStack
;
635 PWDMAUD_DEVICE_INFO DeviceInfo
;
636 PWDMAUD_CLIENT ClientInfo
;
637 NTSTATUS Status
= STATUS_SUCCESS
;
639 PCONTEXT_WRITE Packet
;
640 PFILE_OBJECT FileObject
;
641 IO_STATUS_BLOCK IoStatusBlock
;
643 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
645 //DPRINT("WdmAudWrite entered\n");
647 if (IoStack
->Parameters
.Write
.Length
< sizeof(WDMAUD_DEVICE_INFO
))
649 /* invalid parameter */
650 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.Write
.Length
, sizeof(WDMAUD_DEVICE_INFO
));
651 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
654 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)MmGetMdlVirtualAddress(Irp
->MdlAddress
);
657 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
658 if (!NT_SUCCESS(Status
))
660 DPRINT1("Invalid buffer handle %x\n", DeviceInfo
->hDevice
);
661 return SetIrpIoStatus(Irp
, Status
, 0);
665 //DPRINT("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa);
666 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
668 /* invalid parameter */
669 DPRINT1("Error: device type not set\n");
670 ObDereferenceObject(FileObject
);
671 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
674 if (!IoStack
->FileObject
)
676 /* file object parameter */
677 DPRINT1("Error: file object is not attached\n");
678 ObDereferenceObject(FileObject
);
679 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
681 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
684 /* setup stream context */
685 Packet
= (PCONTEXT_WRITE
)ExAllocatePool(NonPagedPool
, sizeof(CONTEXT_WRITE
));
689 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
692 Packet
->Header
.FrameExtent
= DeviceInfo
->BufferSize
;
693 Packet
->Header
.DataUsed
= DeviceInfo
->BufferSize
;
694 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
695 Packet
->Header
.PresentationTime
.Numerator
= 1;
696 Packet
->Header
.PresentationTime
.Denominator
= 1;
699 Buffer
= ExAllocatePool(NonPagedPool
, DeviceInfo
->BufferSize
);
704 ObDereferenceObject(FileObject
);
705 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
707 Packet
->Header
.Data
= Buffer
;
711 ProbeForRead(DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
, TYPE_ALIGNMENT(char));
712 RtlMoveMemory(Buffer
, DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
);
714 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
716 /* Exception, get the error code */
717 Status
= _SEH2_GetExceptionCode();
721 if (!NT_SUCCESS(Status
))
723 DPRINT1("Invalid buffer supplied\n");
726 ObDereferenceObject(FileObject
);
727 return SetIrpIoStatus(Irp
, Status
, 0);
730 KsStreamIo(FileObject
, NULL
, NULL
, NULL
, NULL
, 0, &IoStatusBlock
, Packet
, sizeof(CONTEXT_WRITE
), KSSTREAM_WRITE
, KernelMode
);
731 ObDereferenceObject(FileObject
);
732 return IoStatusBlock
.Status
;