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_Sysaudio
= {0xCBE3FAA0L
, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
15 IN PDEVICE_OBJECT DeviceObject
,
17 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
18 IN PWDMAUD_CLIENT ClientInfo
)
20 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
22 return WdmAudControlOpenMixer(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
25 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
27 return WdmAudControlOpenWave(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
30 return SetIrpIoStatus(Irp
, STATUS_NOT_SUPPORTED
, sizeof(WDMAUD_DEVICE_INFO
));
34 WdmAudControlDeviceType(
35 IN PDEVICE_OBJECT DeviceObject
,
37 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
38 IN PWDMAUD_CLIENT ClientInfo
)
41 NTSTATUS Status
= STATUS_SUCCESS
;
42 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
44 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
46 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
48 Result
= WdmAudGetMixerDeviceCount();
50 else if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
52 Result
= WdmAudGetWaveInDeviceCount();
54 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
56 Result
= WdmAudGetWaveOutDeviceCount();
59 /* store result count */
60 DeviceInfo
->DeviceCount
= Result
;
62 DPRINT("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
63 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
67 WdmAudControlDeviceState(
68 IN PDEVICE_OBJECT DeviceObject
,
70 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
71 IN PWDMAUD_CLIENT ClientInfo
)
77 PFILE_OBJECT FileObject
;
79 DPRINT("WdmAudControlDeviceState\n");
81 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
82 if (!NT_SUCCESS(Status
))
84 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
85 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
88 Property
.Set
= KSPROPSETID_Connection
;
89 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
90 Property
.Flags
= KSPROPERTY_TYPE_SET
;
92 State
= DeviceInfo
->u
.State
;
94 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
96 ObDereferenceObject(FileObject
);
98 DPRINT("WdmAudControlDeviceState Status %x\n", Status
);
99 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
104 IN PDEVICE_OBJECT DeviceObject
,
106 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
107 IN PWDMAUD_CLIENT ClientInfo
)
109 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
110 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
112 DPRINT("WdmAudCapabilities entered\n");
114 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
116 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
118 Status
= WdmAudMixerCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
120 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
122 Status
= WdmAudWaveCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
125 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
131 IN PDEVICE_OBJECT DeviceObject
,
133 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
134 IN PWDMAUD_CLIENT ClientInfo
)
138 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
140 if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
142 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
143 ZwClose(DeviceInfo
->hDevice
);
144 ClientInfo
->hPins
[Index
].Handle
= NULL
;
145 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
146 return STATUS_SUCCESS
;
148 else if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
150 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
152 ObDereferenceObject(ClientInfo
->hPins
[Index
].NotifyEvent
);
153 ClientInfo
->hPins
[Index
].NotifyEvent
= NULL
;
158 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
159 return STATUS_INVALID_PARAMETER
;
165 IN PDEVICE_OBJECT DeviceObject
,
167 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
168 IN PWDMAUD_CLIENT ClientInfo
)
170 PFILE_OBJECT FileObject
;
173 KSALLOCATOR_FRAMING Framing
;
176 /* Get sysaudio pin file object */
177 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
178 if (!NT_SUCCESS(Status
))
180 DPRINT1("Invalid buffer handle %p\n", DeviceInfo
->hDevice
);
181 return SetIrpIoStatus(Irp
, Status
, 0);
184 /* Setup get framing request */
185 Property
.Id
= KSPROPERTY_CONNECTION_ALLOCATORFRAMING
;
186 Property
.Flags
= KSPROPERTY_TYPE_GET
;
187 Property
.Set
= KSPROPSETID_Connection
;
189 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&Framing
, sizeof(KSALLOCATOR_FRAMING
), &BytesReturned
);
191 if (NT_SUCCESS(Status
))
193 /* Store framesize */
194 DeviceInfo
->u
.FrameSize
= Framing
.FrameSize
;
197 /* Release file object */
198 ObDereferenceObject(FileObject
);
200 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
206 WdmAudGetDeviceInterface(
207 IN PDEVICE_OBJECT DeviceObject
,
209 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
211 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
216 /* get device extension */
217 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
219 /* get device interface string input length */
220 Size
= DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
;
222 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
225 Status
= WdmAudGetPnpNameByIndexAndType(DeviceInfo
->DeviceIndex
, DeviceInfo
->DeviceType
, &Device
);
227 /* check for success */
228 if (!NT_SUCCESS(Status
))
230 /* invalid device id */
231 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
234 /* calculate length */
235 Length
= (wcslen(Device
)+1) * sizeof(WCHAR
);
239 /* store device interface size */
240 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
242 else if (Size
< Length
)
244 /* buffer too small */
245 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
246 return SetIrpIoStatus(Irp
, STATUS_BUFFER_OVERFLOW
, sizeof(WDMAUD_DEVICE_INFO
));
251 RtlMoveMemory(DeviceInfo
->u
.Interface
.DeviceInterfaceString
, Device
, Length
);
255 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
257 else if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
259 if (DeviceInfo
->DeviceIndex
>= WdmAudGetMixerDeviceCount())
261 /* invalid device id */
262 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
265 Status
= WdmAudGetMixerPnpNameByIndex(DeviceInfo
->DeviceIndex
, &Device
);
266 /* check for success */
267 if (!NT_SUCCESS(Status
))
269 /* invalid device id */
270 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
273 /* calculate length */
274 Length
= (wcslen(Device
)+1) * sizeof(WCHAR
);
278 /* store device interface size */
279 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
281 else if (Size
< Length
)
283 /* buffer too small */
284 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
285 return SetIrpIoStatus(Irp
, STATUS_BUFFER_OVERFLOW
, sizeof(WDMAUD_DEVICE_INFO
));
290 RtlMoveMemory(DeviceInfo
->u
.Interface
.DeviceInterfaceString
, Device
, Length
);
292 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
295 return SetIrpIoStatus(Irp
, STATUS_INVALID_DEVICE_REQUEST
, sizeof(WDMAUD_DEVICE_INFO
));
301 IN PDEVICE_OBJECT DeviceObject
,
303 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
308 PFILE_OBJECT FileObject
;
310 DPRINT("WdmAudResetStream\n");
312 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
313 if (!NT_SUCCESS(Status
))
315 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
316 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
319 ResetStream
= DeviceInfo
->u
.ResetStream
;
320 ASSERT(ResetStream
== KSRESET_BEGIN
|| ResetStream
== KSRESET_END
);
322 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_RESET_STATE
, (PVOID
)&ResetStream
, sizeof(KSRESET
), NULL
, 0, &BytesReturned
);
324 ObDereferenceObject(FileObject
);
326 DPRINT("WdmAudResetStream Status %x\n", Status
);
327 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
333 IN PDEVICE_OBJECT DeviceObject
,
336 PIO_STACK_LOCATION IoStack
;
337 PWDMAUD_DEVICE_INFO DeviceInfo
;
338 PWDMAUD_CLIENT ClientInfo
;
340 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
342 DPRINT("WdmAudDeviceControl entered\n");
344 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
346 /* invalid parameter */
347 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
348 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
351 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
353 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
355 /* invalid parameter */
356 DPRINT1("Error: device type not set\n");
357 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
360 if (!IoStack
->FileObject
)
362 /* file object parameter */
363 DPRINT1("Error: file object is not attached\n");
364 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
366 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
368 DPRINT("WdmAudDeviceControl entered\n");
370 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
372 case IOCTL_OPEN_WDMAUD
:
373 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
374 case IOCTL_GETNUMDEVS_TYPE
:
375 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
376 case IOCTL_SETDEVICE_STATE
:
377 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
378 case IOCTL_GETCAPABILITIES
:
379 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
380 case IOCTL_CLOSE_WDMAUD
:
381 return WdmAudIoctlClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
382 case IOCTL_GETFRAMESIZE
:
383 return WdmAudFrameSize(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
384 case IOCTL_GETLINEINFO
:
385 return WdmAudGetLineInfo(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
386 case IOCTL_GETLINECONTROLS
:
387 return WdmAudGetLineControls(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
388 case IOCTL_SETCONTROLDETAILS
:
389 return WdmAudSetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
390 case IOCTL_GETCONTROLDETAILS
:
391 return WdmAudGetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
392 case IOCTL_QUERYDEVICEINTERFACESTRING
:
393 return WdmAudGetDeviceInterface(DeviceObject
, Irp
, DeviceInfo
);
394 case IOCTL_GET_MIXER_EVENT
:
395 return WdmAudGetMixerEvent(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
396 case IOCTL_RESET_STREAM
:
397 return WdmAudResetStream(DeviceObject
, Irp
, DeviceInfo
);
400 case IOCTL_GETVOLUME
:
401 case IOCTL_SETVOLUME
:
403 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
407 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
414 IN PDEVICE_OBJECT DeviceObject
,
418 PWDMAUD_DEVICE_INFO DeviceInfo
;
419 PFILE_OBJECT FileObject
;
420 PIO_STACK_LOCATION IoStack
;
425 /* get current irp stack location */
426 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
428 /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
429 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
432 ASSERT(Irp
->UserBuffer
);
434 /* get the length of the request length */
435 Length
= IoStack
->Parameters
.Write
.Length
;
437 /* store outputbuffer length */
438 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= Length
;
440 /* store mdl address */
441 Mdl
= Irp
->MdlAddress
;
443 /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
444 Irp
->MdlAddress
= NULL
;
446 /* check for success */
448 if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
450 /* probe the write stream irp */
452 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMWRITE
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
456 /* probe the read stream irp */
457 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMREAD
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
460 /* now free the mdl */
463 if (!NT_SUCCESS(Status
))
465 DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status
, Irp
->Cancel
);
466 return SetIrpIoStatus(Irp
, Status
, 0);
469 /* get device info */
470 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
473 /* now get sysaudio file object */
474 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
475 if (!NT_SUCCESS(Status
))
477 DPRINT1("Invalid pin handle %p\n", DeviceInfo
->hDevice
);
478 return SetIrpIoStatus(Irp
, Status
, 0);
481 /* skip current irp stack location */
482 IoSkipCurrentIrpStackLocation(Irp
);
484 /* get next stack location */
485 IoStack
= IoGetNextIrpStackLocation(Irp
);
489 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_READ_STREAM
;
493 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_WRITE_STREAM
;
496 /* attach file object */
497 IoStack
->FileObject
= FileObject
;
498 IoStack
->Parameters
.Write
.Length
= Length
;
499 IoStack
->MajorFunction
= IRP_MJ_WRITE
;
501 /* mark irp as pending */
502 // IoMarkIrpPending(Irp);
503 /* call the driver */
504 Status
= IoCallDriver(IoGetRelatedDeviceObject(FileObject
), Irp
);
506 /* dereference file object */
507 ObDereferenceObject(FileObject
);