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_Connection
= {0x1D58C920L
, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
12 const GUID KSPROPSETID_Sysaudio
= {0xCBE3FAA0L
, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
13 const GUID KSPROPSETID_General
= {0x1464EDA5L
, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
14 const GUID KSINTERFACESETID_Standard
= {0x1A8766A0L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 const GUID KSMEDIUMSETID_Standard
= {0x4747B320L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
16 const GUID KSDATAFORMAT_TYPE_AUDIO
= {0x73647561L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
17 const GUID KSDATAFORMAT_SUBTYPE_PCM
= {0x00000001L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
18 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
,
38 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
39 IN PWDMAUD_CLIENT ClientInfo
)
41 PSYSAUDIO_INSTANCE_INFO InstanceInfo
;
44 ACCESS_MASK DesiredAccess
= 0;
46 KSPIN_CONNECT
* PinConnect
;
47 KSDATAFORMAT_WAVEFORMATEX
* DataFormat
;
49 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
)
51 DPRINT1("FIXME: only waveout devices are supported\n");
52 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
55 InstanceInfo
= ExAllocatePool(NonPagedPool
, sizeof(KSDATAFORMAT_WAVEFORMATEX
) + sizeof(KSPIN_CONNECT
));
59 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
62 InstanceInfo
->Property
.Set
= KSPROPSETID_Sysaudio
;
63 InstanceInfo
->Property
.Id
= KSPROPERTY_SYSAUDIO_INSTANCE_INFO
;
64 InstanceInfo
->Property
.Flags
= KSPROPERTY_TYPE_SET
;
65 InstanceInfo
->Flags
= 0;
66 InstanceInfo
->DeviceNumber
= DeviceInfo
->DeviceIndex
;
68 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)InstanceInfo
, sizeof(SYSAUDIO_INSTANCE_INFO
), NULL
, 0, &BytesReturned
);
70 if (!NT_SUCCESS(Status
))
72 /* failed to acquire audio device */
73 DPRINT1("KsSynchronousIoControlDevice failed with %x\n", Status
);
74 ExFreePool(InstanceInfo
);
75 return SetIrpIoStatus(Irp
, Status
, 0);
78 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
||
79 DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
||
80 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
82 DesiredAccess
|= GENERIC_READ
;
85 if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
||
86 DeviceInfo
->DeviceType
== MIDI_OUT_DEVICE_TYPE
||
87 DeviceInfo
->DeviceType
== AUX_DEVICE_TYPE
||
88 DeviceInfo
->DeviceType
== MIXER_DEVICE_TYPE
)
90 DesiredAccess
|= GENERIC_WRITE
;
93 PinConnect
= (KSPIN_CONNECT
*)InstanceInfo
;
96 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
97 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
98 PinConnect
->Interface
.Flags
= 0;
99 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
100 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
101 PinConnect
->Medium
.Flags
= 0;
102 PinConnect
->PinId
= 0; //FIXME
103 PinConnect
->PinToHandle
= NULL
;
104 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
105 PinConnect
->Priority
.PrioritySubClass
= 1;
108 DataFormat
= (KSDATAFORMAT_WAVEFORMATEX
*) (PinConnect
+ 1);
109 DataFormat
->WaveFormatEx
.wFormatTag
= DeviceInfo
->u
.WaveFormatEx
.wFormatTag
;
110 DataFormat
->WaveFormatEx
.nChannels
= DeviceInfo
->u
.WaveFormatEx
.nChannels
;
111 DataFormat
->WaveFormatEx
.nSamplesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nSamplesPerSec
;
112 DataFormat
->WaveFormatEx
.nBlockAlign
= DeviceInfo
->u
.WaveFormatEx
.nBlockAlign
;
113 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= DeviceInfo
->u
.WaveFormatEx
.nAvgBytesPerSec
;
114 DataFormat
->WaveFormatEx
.wBitsPerSample
= DeviceInfo
->u
.WaveFormatEx
.wBitsPerSample
;
115 DataFormat
->WaveFormatEx
.cbSize
= 0;
116 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
117 DataFormat
->DataFormat
.Flags
= 0;
118 DataFormat
->DataFormat
.Reserved
= 0;
119 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
121 if (DeviceInfo
->u
.WaveFormatEx
.wFormatTag
!= WAVE_FORMAT_PCM
)
124 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
125 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
126 DataFormat
->DataFormat
.SampleSize
= 4;
129 Status
= KsCreatePin(ClientInfo
->hSysAudio
, PinConnect
, DesiredAccess
, &PinHandle
);
130 DPRINT1("KsCreatePin Status %x\n", Status
);
134 ExFreePool(InstanceInfo
);
136 if (NT_SUCCESS(Status
))
138 DeviceInfo
->hDevice
= PinHandle
;
142 DeviceInfo
->hDevice
= NULL
;
145 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
149 WdmAudControlDeviceType(
150 IN PDEVICE_OBJECT DeviceObject
,
152 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
153 IN PWDMAUD_CLIENT ClientInfo
)
156 ULONG Result
, BytesReturned
;
159 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
)
161 DPRINT1("FIXME: only waveout devices are supported\n");
162 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
165 Property
.Set
= KSPROPSETID_Sysaudio
;
166 Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
167 Property
.Flags
= KSPROPERTY_TYPE_GET
;
169 Status
= KsSynchronousIoControlDevice(ClientInfo
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&Result
, sizeof(ULONG
), &BytesReturned
);
171 if (NT_SUCCESS(Status
))
172 DeviceInfo
->DeviceCount
= Result
;
174 DeviceInfo
->DeviceCount
= 0;
176 DPRINT1("WdmAudControlDeviceType Status %x Devices %u\n", Status
, DeviceInfo
->DeviceCount
);
177 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
181 WdmAudControlDeviceState(
182 IN PDEVICE_OBJECT DeviceObject
,
184 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
185 IN PWDMAUD_CLIENT ClientInfo
)
191 PFILE_OBJECT FileObject
;
193 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
)
195 DPRINT1("FIXME: only waveout devices are supported\n");
196 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
199 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_READ
| GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
200 if (!NT_SUCCESS(Status
))
202 DPRINT1("Error: invalid device handle provided %p\n", DeviceInfo
->hDevice
);
203 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
206 Property
.Set
= KSPROPSETID_Connection
;
207 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
208 Property
.Flags
= KSPROPERTY_TYPE_SET
;
210 State
= DeviceInfo
->State
;
212 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesReturned
);
214 ObDereferenceObject(FileObject
);
216 DPRINT1("WdmAudControlDeviceState Status %x\n", Status
);
217 return SetIrpIoStatus(Irp
, Status
, sizeof(WDMAUD_DEVICE_INFO
));
222 WdmAudWriteCompleted(
223 IN PDEVICE_OBJECT DeviceObject
,
227 PWRITE_CONTEXT Context
= (PWRITE_CONTEXT
)Ctx
;
229 Context
->Irp
->IoStatus
.Information
= Context
->Length
;
230 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
231 IoCompleteRequest(Context
->Irp
, IO_SOUND_INCREMENT
);
234 return STATUS_SUCCESS
;
238 WdmAudControlWriteData(
239 IN PDEVICE_OBJECT DeviceObject
,
241 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
242 IN PWDMAUD_CLIENT ClientInfo
)
244 PKSSTREAM_HEADER Packet
;
245 NTSTATUS Status
= STATUS_SUCCESS
;
246 PFILE_OBJECT FileObject
;
247 PWRITE_CONTEXT Context
;
251 Status
= ObReferenceObjectByHandle(DeviceInfo
->hDevice
, GENERIC_WRITE
, IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
252 if (!NT_SUCCESS(Status
))
254 DPRINT1("Invalid buffer handle %x\n", DeviceInfo
->hDevice
);
255 return SetIrpIoStatus(Irp
, Status
, 0);
258 if (DeviceInfo
->DeviceType
!= WAVE_OUT_DEVICE_TYPE
)
260 DPRINT1("FIXME: only waveout devices are supported\n");
261 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
266 ProbeForRead(DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
, TYPE_ALIGNMENT(char));
268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
270 /* Exception, get the error code */
271 Status
= _SEH2_GetExceptionCode();
275 if (!NT_SUCCESS(Status
))
277 DPRINT1("Invalid buffer supplied\n");
278 return SetIrpIoStatus(Irp
, Status
, 0);
281 Buffer
= ExAllocatePool(NonPagedPool
, DeviceInfo
->BufferSize
);
285 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
288 RtlMoveMemory(Buffer
, DeviceInfo
->Buffer
, DeviceInfo
->BufferSize
);
291 Context
= ExAllocatePool(NonPagedPool
, sizeof(WRITE_CONTEXT
));
295 return SetIrpIoStatus(Irp
, STATUS_NO_MEMORY
, 0);
298 /* setup completion context */
300 Context
->Length
= DeviceInfo
->BufferSize
;
302 /* setup stream context */
303 Packet
= (PKSSTREAM_HEADER
)ExAllocatePool(NonPagedPool
, sizeof(KSSTREAM_HEADER
));
304 Packet
->Data
= Buffer
;
305 Packet
->FrameExtent
= DeviceInfo
->BufferSize
;
306 Packet
->DataUsed
= DeviceInfo
->BufferSize
;
307 Packet
->Size
= sizeof(KSSTREAM_HEADER
);
308 Packet
->PresentationTime
.Numerator
= 1;
309 Packet
->PresentationTime
.Denominator
= 1;
310 ASSERT(FileObject
->FsContext
!= NULL
);
313 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_WRITE_STREAM
, (PVOID
)Packet
, sizeof(KSSTREAM_HEADER
), NULL
, 0, &BytesReturned
);
315 DPRINT1("KsSynchronousIoControlDevice result %x\n", Status
);
317 IoMarkIrpPending(Irp
);
318 Irp
->IoStatus
.Information
= DeviceInfo
->BufferSize
;
319 Irp
->IoStatus
.Status
= Status
;
331 IN PDEVICE_OBJECT DeviceObject
,
334 PIO_STACK_LOCATION IoStack
;
335 PWDMAUD_DEVICE_INFO DeviceInfo
;
336 PWDMAUD_CLIENT ClientInfo
;
338 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
340 DPRINT1("WdmAudDeviceControl entered\n");
343 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(WDMAUD_DEVICE_INFO
))
345 /* invalid parameter */
346 DPRINT1("Input buffer too small size %u expected %u\n", IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, sizeof(WDMAUD_DEVICE_INFO
));
347 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
350 DeviceInfo
= (PWDMAUD_DEVICE_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
352 if (DeviceInfo
->DeviceType
< MIN_SOUND_DEVICE_TYPE
|| DeviceInfo
->DeviceType
> MAX_SOUND_DEVICE_TYPE
)
354 /* invalid parameter */
355 DPRINT1("Error: device type not set\n");
356 return SetIrpIoStatus(Irp
, STATUS_INVALID_PARAMETER
, 0);
359 if (!IoStack
->FileObject
)
361 /* file object parameter */
362 DPRINT1("Error: file object is not attached\n");
363 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
365 ClientInfo
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
367 DPRINT1("WdmAudDeviceControl entered\n");
369 switch(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
371 case IOCTL_OPEN_WDMAUD
:
372 return WdmAudControlOpen(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
373 case IOCTL_GETNUMDEVS_TYPE
:
374 return WdmAudControlDeviceType(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
375 case IOCTL_SETDEVICE_STATE
:
376 return WdmAudControlDeviceState(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
377 case IOCTL_WRITEDATA
:
378 return WdmAudControlWriteData(DeviceObject
, Irp
, DeviceInfo
, ClientInfo
);
380 case IOCTL_CLOSE_WDMAUD
:
382 case IOCTL_GETVOLUME
:
383 case IOCTL_SETVOLUME
:
384 case IOCTL_GETCAPABILITIES
:
385 DPRINT1("Unhandeled %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
389 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);