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
15 const GUID KSPROPSETID_Sysaudio
= {0xCBE3FAA0L
, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
19 IN PDEVICE_OBJECT DeviceObject
,
21 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
22 IN PWDMAUD_CLIENT ClientInfo
)
24 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
26 return WdmAudControlOpenMixer(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
29 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
31 return WdmAudControlOpenWave(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
34 if (DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
)
36 return WdmAudControlOpenMidi(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
= WdmAudGetMixerDeviceCount();
60 else if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
62 Result
= WdmAudGetWaveInDeviceCount();
64 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
66 Result
= WdmAudGetWaveOutDeviceCount();
68 else if (DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
)
70 Result
= WdmAudGetMidiInDeviceCount();
72 else if (DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
)
74 Result
= WdmAudGetMidiOutDeviceCount();
78 /* store result count */
79 DeviceInfo
->DeviceCount
= Result
;
81 DPRINT("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
82 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
86 WdmAudControlDeviceState(
87 IN PDEVICE_OBJECT DeviceObject
,
89 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
90 IN PWDMAUD_CLIENT ClientInfo
)
96 PFILE_OBJECT FileObject
;
98 DPRINT("WdmAudControlDeviceState\n");
100 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
104 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
107 Property
.Set
= KSPROPSETID_Connection
;
108 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
109 Property
.Flags
= KSPROPERTY_TYPE_SET
;
111 State
= DeviceInfo
->u
.State
;
113 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
115 ObDereferenceObject(FileObject
);
117 DPRINT("WdmAudControlDeviceState Status %x\n", Status
);
118 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
123 IN PDEVICE_OBJECT DeviceObject
,
125 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
126 IN PWDMAUD_CLIENT ClientInfo
)
128 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
129 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
131 DPRINT("WdmAudCapabilities entered\n");
133 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
135 if (DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
137 Status
= WdmAudMixerCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
139 else if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
141 Status
= WdmAudWaveCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
143 else if (DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
)
145 Status
= WdmAudMidiCapabilities(DeviceObject
, DeviceInfo
, ClientInfo
, DeviceExtension
);
148 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
154 IN PDEVICE_OBJECT DeviceObject
,
156 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
157 IN PWDMAUD_CLIENT ClientInfo
)
161 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
163 if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
165 DPRINT1("Closing device %p\n", DeviceInfo
->hDevice
);
166 ZwClose(DeviceInfo
->hDevice
);
167 ClientInfo
->hPins
[Index
].Handle
= NULL
;
168 SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
169 return STATUS_SUCCESS
;
171 else if (ClientInfo
->hPins
[Index
].Handle
== DeviceInfo
->hDevice
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
173 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
175 ObDereferenceObject(ClientInfo
->hPins
[Index
].NotifyEvent
);
176 ClientInfo
->hPins
[Index
].NotifyEvent
= NULL
;
181 SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, sizeof(WDMAUD_DEVICE_INFO
));
182 return STATUS_INVALID_PARAMETER
;
188 IN PDEVICE_OBJECT DeviceObject
,
190 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
191 IN PWDMAUD_CLIENT ClientInfo
)
193 PFILE_OBJECT FileObject
;
196 KSALLOCATOR_FRAMING Framing
;
199 /* Get sysaudio pin file object */
200 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
201 if (!NT_SUCCESS(Status
))
203 DPRINT1("Invalid buffer handle %p\n", DeviceInfo
->hDevice
);
204 return SetIrpIoStatus(Irp
, Status
, 0);
207 /* Setup get framing request */
208 Property
.Id
= KSPROPERTY_CONNECTION_ALLOCATORFRAMING
;
209 Property
.Flags
= KSPROPERTY_TYPE_GET
;
210 Property
.Set
= KSPROPSETID_Connection
;
212 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&Framing
, sizeof(KSALLOCATOR_FRAMING
), &BytesReturned
);
214 if (NT_SUCCESS(Status
))
216 /* Store framesize */
217 DeviceInfo
->u
.FrameSize
= Framing
.FrameSize
;
220 /* Release file object */
221 ObDereferenceObject(FileObject
);
223 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
229 WdmAudGetDeviceInterface(
230 IN PDEVICE_OBJECT DeviceObject
,
232 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
234 //PWDMAUD_DEVICE_EXTENSION DeviceExtension;
239 /* get device extension */
240 //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
242 /* get device interface string input length */
243 Size
= DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
;
246 Status
= WdmAudGetPnpNameByIndexAndType(DeviceInfo
->DeviceIndex
, DeviceInfo
->DeviceType
, &Device
);
248 /* check for success */
249 if (!NT_SUCCESS(Status
))
251 /* invalid device id */
252 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
255 /* calculate length */
256 Length
= (wcslen(Device
)+1) * sizeof(WCHAR
);
260 /* store device interface size */
261 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
263 else if (Size
< Length
)
265 /* buffer too small */
266 DeviceInfo
->u
.Interface
.DeviceInterfaceStringSize
= Length
;
267 return SetIrpIoStatus(Irp
, STATUS_BUFFER_OVERFLOW
, sizeof(WDMAUD_DEVICE_INFO
));
272 RtlMoveMemory(DeviceInfo
->u
.Interface
.DeviceInterfaceString
, Device
, Length
);
276 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
282 IN PDEVICE_OBJECT DeviceObject
,
284 IN PWDMAUD_DEVICE_INFO DeviceInfo
)
289 PFILE_OBJECT FileObject
;
291 DPRINT("WdmAudResetStream\n");
293 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
294 if (!NT_SUCCESS(Status
))
296 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo
->hDevice
, DeviceInfo
->DeviceType
);
297 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
300 ResetStream
= DeviceInfo
->u
.ResetStream
;
301 ASSERT(ResetStream
== KSRESET_BEGIN
|| ResetStream
== KSRESET_END
);
303 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_RESET_STATE
, (PVOID
)&ResetStream
, sizeof(KSRESET
), NULL
, 0, &BytesReturned
);
305 ObDereferenceObject(FileObject
);
307 DPRINT("WdmAudResetStream Status %x\n", Status
);
308 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
314 IN PDEVICE_OBJECT DeviceObject
,
317 PIO_STACK_LOCATION IoStack
;
318 PWDMAUD_DEVICE_INFO DeviceInfo
;
319 PWDMAUD_CLIENT ClientInfo
;
321 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
323 DPRINT("WdmAudDeviceControl entered\n");
325 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
327 /* invalid parameter */
328 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
329 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
332 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
334 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
336 /* invalid parameter */
337 DPRINT1("Error: device type not set\n");
338 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
341 if (!IoStack
->FileObject
|| !IoStack
->FileObject
->FsContext
)
343 /* file object parameter */
344 DPRINT1("Error: file object is not attached\n");
345 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
347 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
349 DPRINT("WdmAudDeviceControl entered\n");
351 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
353 case IOCTL_OPEN_WDMAUD
:
354 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
355 case IOCTL_GETNUMDEVS_TYPE
:
356 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
357 case IOCTL_SETDEVICE_STATE
:
358 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
359 case IOCTL_GETCAPABILITIES
:
360 return WdmAudCapabilities(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
361 case IOCTL_CLOSE_WDMAUD
:
362 return WdmAudIoctlClose(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
363 case IOCTL_GETFRAMESIZE
:
364 return WdmAudFrameSize(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
365 case IOCTL_GETLINEINFO
:
366 return WdmAudGetLineInfo(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
367 case IOCTL_GETLINECONTROLS
:
368 return WdmAudGetLineControls(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
369 case IOCTL_SETCONTROLDETAILS
:
370 return WdmAudSetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
371 case IOCTL_GETCONTROLDETAILS
:
372 return WdmAudGetControlDetails(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
373 case IOCTL_QUERYDEVICEINTERFACESTRING
:
374 return WdmAudGetDeviceInterface(DeviceObject
, Irp
, DeviceInfo
);
375 case IOCTL_GET_MIXER_EVENT
:
376 return WdmAudGetMixerEvent(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
377 case IOCTL_RESET_STREAM
:
378 return WdmAudResetStream(DeviceObject
, Irp
, DeviceInfo
);
381 case IOCTL_GETVOLUME
:
382 case IOCTL_SETVOLUME
:
384 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
388 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
394 PDEVICE_OBJECT DeviceObject
,
398 PKSSTREAM_HEADER Header
;
401 PWDMAUD_COMPLETION_CONTEXT Context
= (PWDMAUD_COMPLETION_CONTEXT
)Ctx
;
403 /* get stream header */
404 Header
= (PKSSTREAM_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
409 /* time to free all allocated mdls */
410 Mdl
= Irp
->MdlAddress
;
425 Irp
->MdlAddress
= NULL
;
427 /* check if mdl is locked */
428 if (Context
->Mdl
->MdlFlags
& MDL_PAGES_LOCKED
)
431 MmUnlockPages(Context
->Mdl
);
434 /* now free the mdl */
435 IoFreeMdl(Context
->Mdl
);
437 DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n", Irp
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
, Length
);
439 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
442 Irp
->IoStatus
.Information
= 0;
448 return STATUS_SUCCESS
;
454 IN PDEVICE_OBJECT DeviceObject
,
458 PWDMAUD_DEVICE_INFO DeviceInfo
;
459 PFILE_OBJECT FileObject
;
460 PIO_STACK_LOCATION IoStack
;
464 PWDMAUD_COMPLETION_CONTEXT Context
;
466 /* allocate completion context */
467 Context
= AllocateItem(NonPagedPool
, sizeof(WDMAUD_COMPLETION_CONTEXT
));
471 /* not enough memory */
472 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
473 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
476 return STATUS_INSUFFICIENT_RESOURCES
;
479 /* get current irp stack location */
480 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
482 /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
483 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
486 ASSERT(Irp
->UserBuffer
);
488 /* get the length of the request length */
489 Length
= IoStack
->Parameters
.Write
.Length
;
491 /* store outputbuffer length */
492 IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
= Length
;
495 Context
->Length
= Length
;
496 Context
->Function
= (IoStack
->MajorFunction
== IRP_MJ_WRITE
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
);
497 Context
->Mdl
= Irp
->MdlAddress
;
499 /* store mdl address */
500 Mdl
= Irp
->MdlAddress
;
502 /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
503 Irp
->MdlAddress
= NULL
;
505 /* check for success */
507 if (IoStack
->MajorFunction
== IRP_MJ_WRITE
)
509 /* probe the write stream irp */
511 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMWRITE
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
515 /* probe the read stream irp */
516 Status
= KsProbeStreamIrp(Irp
, KSPROBE_STREAMREAD
| KSPROBE_ALLOCATEMDL
| KSPROBE_PROBEANDLOCK
, Length
);
519 if (!NT_SUCCESS(Status
))
521 DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status
, Irp
->Cancel
);
522 Irp
->MdlAddress
= Mdl
;
523 return SetIrpIoStatus(Irp
, Status
, 0);
526 /* get device info */
527 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
530 /* now get sysaudio file object */
531 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
532 if (!NT_SUCCESS(Status
))
534 DPRINT1("Invalid pin handle %p\n", DeviceInfo
->hDevice
);
535 return SetIrpIoStatus(Irp
, Status
, 0);
538 /* skip current irp stack location */
539 IoSkipCurrentIrpStackLocation(Irp
);
541 /* get next stack location */
542 IoStack
= IoGetNextIrpStackLocation(Irp
);
546 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_READ_STREAM
;
550 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_KS_WRITE_STREAM
;
553 /* attach file object */
554 IoStack
->FileObject
= FileObject
;
555 IoStack
->Parameters
.Write
.Length
= Length
;
556 IoStack
->MajorFunction
= IRP_MJ_WRITE
;
558 IoSetCompletionRoutine(Irp
, IoCompletion
, (PVOID
)Context
, TRUE
, TRUE
, TRUE
);
561 /* mark irp as pending */
562 // IoMarkIrpPending(Irp);
563 /* call the driver */
564 Status
= IoCallDriver(IoGetRelatedDeviceObject(FileObject
), Irp
);
566 /* dereference file object */
567 ObDereferenceObject(FileObject
);