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}};
25 IN PDEVICE_OBJECT DeviceObject
,
27 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
28 IN PWDMAUD_CLIENT ClientInfo
)
30 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
32 return WdmAudControlOpenMixer(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
35 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
37 return WdmAudControlOpenWave(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
40 return SetIrpIoStatus(Irp
, STATUS_NOT_SUPPORTED
, sizeof(WDMAUD_DEVICE_INFO
));
44 WdmAudControlDeviceType(
45 IN PDEVICE_OBJECT DeviceObject
,
47 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
48 IN PWDMAUD_CLIENT ClientInfo
)
51 NTSTATUS Status
= STATUS_SUCCESS
;
52 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
54 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
56 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
58 Result
= DeviceExtension
->MixerInfoCount
;
60 else if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
62 Result
= DeviceExtension
->WaveOutDeviceCount
;
64 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
66 Result
= DeviceExtension
->WaveInDeviceCount
;
69 /* store result count */
70 DeviceInfo
->DeviceCount
= Result
;
72 DPRINT("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
73 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
77 WdmAudControlDeviceState(
78 IN PDEVICE_OBJECT DeviceObject
,
80 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
81 IN PWDMAUD_CLIENT ClientInfo
)
87 PFILE_OBJECT FileObject
;
89 DPRINT("WdmAudControlDeviceState\n");
91 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
92 if (!NT_SUCCESS(Status
))
94 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
95 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
98 Property
.Set
= KSPROPSETID_Connection
;
99 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
100 Property
.Flags
= KSPROPERTY_TYPE_SET
;
102 State
= DeviceInfo
->u
.State
;
104 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
106 ObDereferenceObject(FileObject
);
108 DPRINT("WdmAudControlDeviceState Status %x\n", Status
);
109 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
114 IN PDEVICE_OBJECT DeviceObject
,
116 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
117 IN PWDMAUD_CLIENT ClientInfo
)
119 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
120 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
122 DPRINT("WdmAudCapabilities entered\n");
124 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
126 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
128 Status
= WdmAudMixerCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
130 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
132 Status
= WdmAudWaveCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
135 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
141 IN PDEVICE_OBJECT DeviceObject
,
143 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
144 IN PWDMAUD_CLIENT ClientInfo
)
148 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
150 if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
152 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
153 ZwClose(DeviceInfo
->hDevice
);
154 ClientInfo
->hPins
[Index
].Handle
= NULL
;
155 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
156 return STATUS_SUCCESS
;
158 else if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
160 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
162 ObDereferenceObject(ClientInfo
->hPins
[Index
].NotifyEvent
);
163 ClientInfo
->hPins
[Index
].NotifyEvent
= NULL
;
168 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
169 return STATUS_INVALID_PARAMETER
;
175 IN PDEVICE_OBJECT DeviceObject
,
177 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
178 IN PWDMAUD_CLIENT ClientInfo
)
180 PFILE_OBJECT FileObject
;
183 KSALLOCATOR_FRAMING Framing
;
186 /* Get sysaudio pin file object */
187 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
188 if (!NT_SUCCESS(Status
))
190 DPRINT1("Invalid buffer handle %p\n", DeviceInfo
->hDevice
);
191 return SetIrpIoStatus(Irp
, Status
, 0);
194 /* Setup get framing request */
195 Property
.Id
= KSPROPERTY_CONNECTION_ALLOCATORFRAMING
;
196 Property
.Flags
= KSPROPERTY_TYPE_GET
;
197 Property
.Set
= KSPROPSETID_Connection
;
199 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&Framing
, sizeof(KSALLOCATOR_FRAMING
), &BytesReturned
);
201 if (NT_SUCCESS(Status
))
203 /* Store framesize */
204 DeviceInfo
->u
.FrameSize
= Framing
.FrameSize
;
207 /* Release file object */
208 ObDereferenceObject(FileObject
);
210 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
216 WdmAudGetDeviceInterface(
217 IN PDEVICE_OBJECT DeviceObject
,
219 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
221 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
224 LPWAVE_INFO WaveInfo
;
227 /* get device extension */
228 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
230 /* get device interface string input length */
231 Size
= DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
;
233 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
236 Status
= GetWaveInfoByIndexAndType(DeviceObject
, DeviceInfo
->DeviceIndex
, DeviceInfo
->DeviceType
, &WaveInfo
);
238 /* check for success */
239 if (!NT_SUCCESS(Status
))
241 /* invalid device id */
242 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
245 Status
= GetSysAudioDevicePnpName(DeviceObject
, WaveInfo
->FilterId
, &Device
);
246 /* check for success */
247 if (!NT_SUCCESS(Status
))
249 /* invalid device id */
250 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
253 /* calculate length */
254 Length
= (wcslen(Device
)+1) * sizeof(WCHAR
);
258 /* store device interface size */
259 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
261 else if (Size
< Length
)
263 /* buffer too small */
264 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
265 return SetIrpIoStatus(Irp
, STATUS_BUFFER_OVERFLOW
, sizeof(WDMAUD_DEVICE_INFO
));
270 RtlMoveMemory(DeviceInfo
->u
.Interface
.DeviceInterfaceString
, Device
, Length
);
274 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
276 else if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
278 if (DeviceInfo
->DeviceIndex
>= DeviceExtension
->MixerInfoCount
)
280 /* invalid device id */
281 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
284 Status
= GetSysAudioDevicePnpName(DeviceObject
, DeviceExtension
->MixerInfo
[DeviceInfo
->DeviceIndex
].DeviceIndex
, &Device
);
285 /* check for success */
286 if (!NT_SUCCESS(Status
))
288 /* invalid device id */
289 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
292 /* calculate length */
293 Length
= (wcslen(Device
)+1) * sizeof(WCHAR
);
297 /* store device interface size */
298 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
300 else if (Size
< Length
)
302 /* buffer too small */
303 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
304 return SetIrpIoStatus(Irp
, STATUS_BUFFER_OVERFLOW
, sizeof(WDMAUD_DEVICE_INFO
));
309 RtlMoveMemory(DeviceInfo
->u
.Interface
.DeviceInterfaceString
, Device
, Length
);
313 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
316 return SetIrpIoStatus(Irp
, STATUS_INVALID_DEVICE_REQUEST
, sizeof(WDMAUD_DEVICE_INFO
));
322 IN PDEVICE_OBJECT DeviceObject
,
324 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
329 PFILE_OBJECT FileObject
;
331 DPRINT("WdmAudResetStream\n");
333 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
334 if (!NT_SUCCESS(Status
))
336 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
337 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
340 ResetStream
= DeviceInfo
->u
.ResetStream
;
341 ASSERT(ResetStream
== KSRESET_BEGIN
|| ResetStream
== KSRESET_END
);
343 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_RESET_STATE
, (PVOID
)&ResetStream
, sizeof(KSRESET
), NULL
, 0, &BytesReturned
);
345 ObDereferenceObject(FileObject
);
347 DPRINT("WdmAudResetStream Status %x\n", Status
);
348 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
354 IN PDEVICE_OBJECT DeviceObject
,
357 PIO_STACK_LOCATION IoStack
;
358 PWDMAUD_DEVICE_INFO DeviceInfo
;
359 PWDMAUD_CLIENT ClientInfo
;
361 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
363 DPRINT("WdmAudDeviceControl entered\n");
365 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
367 /* invalid parameter */
368 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
369 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
372 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
374 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
376 /* invalid parameter */
377 DPRINT1("Error: device type not set\n");
378 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
381 if (!IoStack
->FileObject
)
383 /* file object parameter */
384 DPRINT1("Error: file object is not attached\n");
385 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
387 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
389 DPRINT("WdmAudDeviceControl entered\n");
391 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
393 case IOCTL_OPEN_WDMAUD
:
394 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
395 case IOCTL_GETNUMDEVS_TYPE
:
396 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
397 case IOCTL_SETDEVICE_STATE
:
398 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
399 case IOCTL_GETCAPABILITIES
:
400 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
401 case IOCTL_CLOSE_WDMAUD
:
402 return WdmAudIoctlClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
403 case IOCTL_GETFRAMESIZE
:
404 return WdmAudFrameSize(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
405 case IOCTL_GETLINEINFO
:
406 return WdmAudGetLineInfo(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
407 case IOCTL_GETLINECONTROLS
:
408 return WdmAudGetLineControls(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
409 case IOCTL_SETCONTROLDETAILS
:
410 return WdmAudSetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
411 case IOCTL_GETCONTROLDETAILS
:
412 return WdmAudGetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
413 case IOCTL_QUERYDEVICEINTERFACESTRING
:
414 return WdmAudGetDeviceInterface(DeviceObject
, Irp
, DeviceInfo
);
415 case IOCTL_GET_MIXER_EVENT
:
416 return WdmAudGetMixerEvent(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
417 case IOCTL_RESET_STREAM
:
418 return WdmAudResetStream(DeviceObject
, Irp
, DeviceInfo
);
421 case IOCTL_GETVOLUME
:
422 case IOCTL_SETVOLUME
:
424 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
428 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
435 IN PDEVICE_OBJECT DeviceObject
,
439 PWDMAUD_DEVICE_INFO DeviceInfo
;
440 PFILE_OBJECT FileObject
;
441 PIO_STACK_LOCATION IoStack
;
446 /* get current irp stack location */
447 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
449 /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
450 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
453 ASSERT(Irp
->UserBuffer
);
455 /* get the length of the request length */
456 Length
= IoStack
->Parameters
.Write
.Length
;
458 /* store outputbuffer length */
459 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= Length
;
461 /* store mdl address */
462 Mdl
= Irp
->MdlAddress
;
464 /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
465 Irp
->MdlAddress
= NULL
;
467 /* check for success */
469 if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
471 /* probe the write stream irp */
473 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMWRITE
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
477 /* probe the read stream irp */
478 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMREAD
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
481 /* now free the mdl */
484 if (!NT_SUCCESS(Status
))
486 DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status
, Irp
->Cancel
);
487 return SetIrpIoStatus(Irp
, Status
, 0);
490 /* get device info */
491 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
494 /* now get sysaudio file object */
495 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
496 if (!NT_SUCCESS(Status
))
498 DPRINT1("Invalid pin handle %p\n", DeviceInfo
->hDevice
);
499 return SetIrpIoStatus(Irp
, Status
, 0);
502 /* skip current irp stack location */
503 IoSkipCurrentIrpStackLocation(Irp
);
505 /* get next stack location */
506 IoStack
= IoGetNextIrpStackLocation(Irp
);
510 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_READ_STREAM
;
514 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_WRITE_STREAM
;
517 /* attach file object */
518 IoStack
->FileObject
= FileObject
;
519 IoStack
->Parameters
.Write
.Length
= Length
;
520 IoStack
->MajorFunction
= IRP_MJ_WRITE
;
522 /* mark irp as pending */
523 // IoMarkIrpPending(Irp);
524 /* call the driver */
525 Status
= IoCallDriver(IoGetRelatedDeviceObject(FileObject
), Irp
);
527 /* dereference file object */
528 ObDereferenceObject(FileObject
);