1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS Kernel Streaming
4c2c66affSColin Finck * FILE: drivers/wdm/audio/legacy/wdmaud/deviface.c
5c2c66affSColin Finck * PURPOSE: System Audio graph builder
6c2c66affSColin Finck * PROGRAMMER: Andrew Greenwood
7c2c66affSColin Finck * Johannes Anderwald
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck #include "wdmaud.h"
11c2c66affSColin Finck
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck
15c2c66affSColin Finck const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
16c2c66affSColin Finck
17c2c66affSColin Finck NTSTATUS
WdmAudControlOpen(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)18c2c66affSColin Finck WdmAudControlOpen(
19c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
20c2c66affSColin Finck IN PIRP Irp,
21c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
22c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
23c2c66affSColin Finck {
24c2c66affSColin Finck if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
25c2c66affSColin Finck {
26c2c66affSColin Finck return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo);
27c2c66affSColin Finck }
28c2c66affSColin Finck
29c2c66affSColin Finck if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
30c2c66affSColin Finck {
31c2c66affSColin Finck return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
32c2c66affSColin Finck }
33c2c66affSColin Finck
34c2c66affSColin Finck if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
35c2c66affSColin Finck {
36c2c66affSColin Finck return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo);
37c2c66affSColin Finck }
38c2c66affSColin Finck
39c2c66affSColin Finck
40c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
41c2c66affSColin Finck }
42c2c66affSColin Finck
43c2c66affSColin Finck NTSTATUS
WdmAudControlDeviceType(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)44c2c66affSColin Finck WdmAudControlDeviceType(
45c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
46c2c66affSColin Finck IN PIRP Irp,
47c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
48c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
49c2c66affSColin Finck {
50c2c66affSColin Finck ULONG Result = 0;
51c2c66affSColin Finck
52c2c66affSColin Finck if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
53c2c66affSColin Finck {
54c2c66affSColin Finck Result = WdmAudGetMixerDeviceCount();
55c2c66affSColin Finck }
56c2c66affSColin Finck else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
57c2c66affSColin Finck {
58c2c66affSColin Finck Result = WdmAudGetWaveOutDeviceCount();
59c2c66affSColin Finck }
60c2c66affSColin Finck else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
61c2c66affSColin Finck {
62c2c66affSColin Finck Result = WdmAudGetWaveInDeviceCount();
63c2c66affSColin Finck }
64c2c66affSColin Finck else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
65c2c66affSColin Finck {
66c2c66affSColin Finck Result = WdmAudGetMidiInDeviceCount();
67c2c66affSColin Finck }
68c2c66affSColin Finck else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
69c2c66affSColin Finck {
70c2c66affSColin Finck Result = WdmAudGetMidiOutDeviceCount();
71c2c66affSColin Finck }
72c2c66affSColin Finck
73c2c66affSColin Finck
74c2c66affSColin Finck /* store result count */
75c2c66affSColin Finck DeviceInfo->DeviceCount = Result;
76c2c66affSColin Finck
77c2c66affSColin Finck DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceCount);
78c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
79c2c66affSColin Finck }
80c2c66affSColin Finck
81c2c66affSColin Finck NTSTATUS
WdmAudControlDeviceState(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)82c2c66affSColin Finck WdmAudControlDeviceState(
83c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
84c2c66affSColin Finck IN PIRP Irp,
85c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
86c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
87c2c66affSColin Finck {
88c2c66affSColin Finck KSPROPERTY Property;
89c2c66affSColin Finck KSSTATE State;
90c2c66affSColin Finck NTSTATUS Status;
91c2c66affSColin Finck ULONG BytesReturned;
92c2c66affSColin Finck PFILE_OBJECT FileObject;
93c2c66affSColin Finck
94c2c66affSColin Finck DPRINT("WdmAudControlDeviceState\n");
95c2c66affSColin Finck
96c2c66affSColin Finck Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
97c2c66affSColin Finck if (!NT_SUCCESS(Status))
98c2c66affSColin Finck {
99c2c66affSColin Finck DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
100c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
101c2c66affSColin Finck }
102c2c66affSColin Finck
103c2c66affSColin Finck Property.Set = KSPROPSETID_Connection;
104c2c66affSColin Finck Property.Id = KSPROPERTY_CONNECTION_STATE;
105c2c66affSColin Finck Property.Flags = KSPROPERTY_TYPE_SET;
106c2c66affSColin Finck
107c2c66affSColin Finck State = DeviceInfo->u.State;
108c2c66affSColin Finck
109c2c66affSColin Finck Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
110c2c66affSColin Finck
111c2c66affSColin Finck ObDereferenceObject(FileObject);
112c2c66affSColin Finck
113c2c66affSColin Finck DPRINT("WdmAudControlDeviceState Status %x\n", Status);
114c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
115c2c66affSColin Finck }
116c2c66affSColin Finck
117c2c66affSColin Finck NTSTATUS
WdmAudCapabilities(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)118c2c66affSColin Finck WdmAudCapabilities(
119c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
120c2c66affSColin Finck IN PIRP Irp,
121c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
122c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
123c2c66affSColin Finck {
124c2c66affSColin Finck PWDMAUD_DEVICE_EXTENSION DeviceExtension;
125c2c66affSColin Finck NTSTATUS Status = STATUS_UNSUCCESSFUL;
126c2c66affSColin Finck
127c2c66affSColin Finck DPRINT("WdmAudCapabilities entered\n");
128c2c66affSColin Finck
129c2c66affSColin Finck DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
130c2c66affSColin Finck
131c2c66affSColin Finck if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
132c2c66affSColin Finck {
133c2c66affSColin Finck Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
134c2c66affSColin Finck }
135c2c66affSColin Finck else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
136c2c66affSColin Finck {
137c2c66affSColin Finck Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
138c2c66affSColin Finck }
139c2c66affSColin Finck else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
140c2c66affSColin Finck {
141c2c66affSColin Finck Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
142c2c66affSColin Finck }
143c2c66affSColin Finck
144c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
145c2c66affSColin Finck }
146c2c66affSColin Finck
147c2c66affSColin Finck NTSTATUS
148c2c66affSColin Finck NTAPI
WdmAudIoctlClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)149c2c66affSColin Finck WdmAudIoctlClose(
150c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
151c2c66affSColin Finck IN PIRP Irp,
152c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
153c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
154c2c66affSColin Finck {
155c2c66affSColin Finck ULONG Index;
156c2c66affSColin Finck
157c2c66affSColin Finck for(Index = 0; Index < ClientInfo->NumPins; Index++)
158c2c66affSColin Finck {
159c2c66affSColin Finck if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE)
160c2c66affSColin Finck {
161c2c66affSColin Finck DPRINT1("Closing device %p\n", DeviceInfo->hDevice);
162c2c66affSColin Finck ZwClose(DeviceInfo->hDevice);
163c2c66affSColin Finck ClientInfo->hPins[Index].Handle = NULL;
164c2c66affSColin Finck SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
165c2c66affSColin Finck return STATUS_SUCCESS;
166c2c66affSColin Finck }
167c2c66affSColin Finck else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
168c2c66affSColin Finck {
169c2c66affSColin Finck DPRINT1("Closing mixer %p\n", DeviceInfo->hDevice);
170c2c66affSColin Finck return WdmAudControlCloseMixer(DeviceObject, Irp, DeviceInfo, ClientInfo, Index);
171c2c66affSColin Finck }
172c2c66affSColin Finck }
173c2c66affSColin Finck
174c2c66affSColin Finck SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
175c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
176c2c66affSColin Finck }
177c2c66affSColin Finck
178c2c66affSColin Finck NTSTATUS
179c2c66affSColin Finck NTAPI
WdmAudFrameSize(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo,IN PWDMAUD_CLIENT ClientInfo)180c2c66affSColin Finck WdmAudFrameSize(
181c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
182c2c66affSColin Finck IN PIRP Irp,
183c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo,
184c2c66affSColin Finck IN PWDMAUD_CLIENT ClientInfo)
185c2c66affSColin Finck {
186c2c66affSColin Finck PFILE_OBJECT FileObject;
187c2c66affSColin Finck KSPROPERTY Property;
188c2c66affSColin Finck ULONG BytesReturned;
189c2c66affSColin Finck KSALLOCATOR_FRAMING Framing;
190c2c66affSColin Finck NTSTATUS Status;
191c2c66affSColin Finck
192c2c66affSColin Finck /* Get sysaudio pin file object */
193c2c66affSColin Finck Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
194c2c66affSColin Finck if (!NT_SUCCESS(Status))
195c2c66affSColin Finck {
196c2c66affSColin Finck DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
197c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, 0);
198c2c66affSColin Finck }
199c2c66affSColin Finck
200c2c66affSColin Finck /* Setup get framing request */
201c2c66affSColin Finck Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
202c2c66affSColin Finck Property.Flags = KSPROPERTY_TYPE_GET;
203c2c66affSColin Finck Property.Set = KSPROPSETID_Connection;
204c2c66affSColin Finck
205c2c66affSColin Finck Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
206c2c66affSColin Finck /* Did we succeed */
207c2c66affSColin Finck if (NT_SUCCESS(Status))
208c2c66affSColin Finck {
209c2c66affSColin Finck /* Store framesize */
210c2c66affSColin Finck DeviceInfo->u.FrameSize = Framing.FrameSize;
211c2c66affSColin Finck }
212c2c66affSColin Finck
213c2c66affSColin Finck /* Release file object */
214c2c66affSColin Finck ObDereferenceObject(FileObject);
215c2c66affSColin Finck
216c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
217c2c66affSColin Finck
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck NTSTATUS
221c2c66affSColin Finck NTAPI
WdmAudGetDeviceInterface(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo)222c2c66affSColin Finck WdmAudGetDeviceInterface(
223c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
224c2c66affSColin Finck IN PIRP Irp,
225c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo)
226c2c66affSColin Finck {
227c2c66affSColin Finck NTSTATUS Status;
228c2c66affSColin Finck LPWSTR Device;
229c2c66affSColin Finck ULONG Size, Length;
230c2c66affSColin Finck
231c2c66affSColin Finck /* get device interface string input length */
232c2c66affSColin Finck Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
233c2c66affSColin Finck
234c2c66affSColin Finck /* get mixer info */
235c2c66affSColin Finck Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
236c2c66affSColin Finck
237c2c66affSColin Finck /* check for success */
238c2c66affSColin Finck if (!NT_SUCCESS(Status))
239c2c66affSColin Finck {
240c2c66affSColin Finck /* invalid device id */
241c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
242c2c66affSColin Finck }
243c2c66affSColin Finck
244c2c66affSColin Finck /* calculate length */
245c2c66affSColin Finck Length = (wcslen(Device)+1) * sizeof(WCHAR);
246c2c66affSColin Finck
247c2c66affSColin Finck if (!Size)
248c2c66affSColin Finck {
249c2c66affSColin Finck /* store device interface size */
250c2c66affSColin Finck DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
251c2c66affSColin Finck }
252c2c66affSColin Finck else if (Size < Length)
253c2c66affSColin Finck {
254c2c66affSColin Finck /* buffer too small */
255c2c66affSColin Finck DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
256c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
257c2c66affSColin Finck }
258c2c66affSColin Finck else
259c2c66affSColin Finck {
260c2c66affSColin Finck //FIXME SEH
261c2c66affSColin Finck RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
262c2c66affSColin Finck }
263c2c66affSColin Finck
264c2c66affSColin Finck FreeItem(Device);
265c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
266c2c66affSColin Finck }
267c2c66affSColin Finck
268c2c66affSColin Finck NTSTATUS
269c2c66affSColin Finck NTAPI
WdmAudResetStream(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PWDMAUD_DEVICE_INFO DeviceInfo)270c2c66affSColin Finck WdmAudResetStream(
271c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
272c2c66affSColin Finck IN PIRP Irp,
273c2c66affSColin Finck IN PWDMAUD_DEVICE_INFO DeviceInfo)
274c2c66affSColin Finck {
275c2c66affSColin Finck KSRESET ResetStream;
276c2c66affSColin Finck NTSTATUS Status;
277c2c66affSColin Finck ULONG BytesReturned;
278c2c66affSColin Finck PFILE_OBJECT FileObject;
279c2c66affSColin Finck
280c2c66affSColin Finck DPRINT("WdmAudResetStream\n");
281c2c66affSColin Finck
282c2c66affSColin Finck Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
283c2c66affSColin Finck if (!NT_SUCCESS(Status))
284c2c66affSColin Finck {
285c2c66affSColin Finck DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
286c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
287c2c66affSColin Finck }
288c2c66affSColin Finck
289c2c66affSColin Finck ResetStream = DeviceInfo->u.ResetStream;
290c2c66affSColin Finck ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END);
291c2c66affSColin Finck
292c2c66affSColin Finck Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned);
293c2c66affSColin Finck
294c2c66affSColin Finck ObDereferenceObject(FileObject);
295c2c66affSColin Finck
296c2c66affSColin Finck DPRINT("WdmAudResetStream Status %x\n", Status);
297c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
298c2c66affSColin Finck }
299c2c66affSColin Finck
300c2c66affSColin Finck NTSTATUS
301c2c66affSColin Finck NTAPI
WdmAudDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)302c2c66affSColin Finck WdmAudDeviceControl(
303c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
304c2c66affSColin Finck IN PIRP Irp)
305c2c66affSColin Finck {
306c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
307c2c66affSColin Finck PWDMAUD_DEVICE_INFO DeviceInfo;
308c2c66affSColin Finck PWDMAUD_CLIENT ClientInfo;
309c2c66affSColin Finck
310c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp);
311c2c66affSColin Finck
312c2c66affSColin Finck DPRINT("WdmAudDeviceControl entered\n");
313c2c66affSColin Finck
314c2c66affSColin Finck if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
315c2c66affSColin Finck {
316c2c66affSColin Finck /* invalid parameter */
317c2c66affSColin Finck DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO));
318c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
319c2c66affSColin Finck }
320c2c66affSColin Finck
321c2c66affSColin Finck DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
322c2c66affSColin Finck
323c2c66affSColin Finck if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
324c2c66affSColin Finck {
325c2c66affSColin Finck /* invalid parameter */
326c2c66affSColin Finck DPRINT1("Error: device type not set\n");
327c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
328c2c66affSColin Finck }
329c2c66affSColin Finck
330c2c66affSColin Finck if (!IoStack->FileObject || !IoStack->FileObject->FsContext)
331c2c66affSColin Finck {
332c2c66affSColin Finck /* file object parameter */
333c2c66affSColin Finck DPRINT1("Error: file object is not attached\n");
334c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
335c2c66affSColin Finck }
336c2c66affSColin Finck ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
337c2c66affSColin Finck
338c2c66affSColin Finck DPRINT("WdmAudDeviceControl entered\n");
339c2c66affSColin Finck
340c2c66affSColin Finck switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
341c2c66affSColin Finck {
342c2c66affSColin Finck case IOCTL_OPEN_WDMAUD:
343c2c66affSColin Finck return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo);
344c2c66affSColin Finck case IOCTL_GETNUMDEVS_TYPE:
345c2c66affSColin Finck return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo);
346c2c66affSColin Finck case IOCTL_SETDEVICE_STATE:
347c2c66affSColin Finck return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
348c2c66affSColin Finck case IOCTL_GETCAPABILITIES:
349c2c66affSColin Finck return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
350c2c66affSColin Finck case IOCTL_CLOSE_WDMAUD:
351c2c66affSColin Finck return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
352c2c66affSColin Finck case IOCTL_GETFRAMESIZE:
353c2c66affSColin Finck return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo);
354c2c66affSColin Finck case IOCTL_GETLINEINFO:
355c2c66affSColin Finck return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo);
356c2c66affSColin Finck case IOCTL_GETLINECONTROLS:
357c2c66affSColin Finck return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo);
358c2c66affSColin Finck case IOCTL_SETCONTROLDETAILS:
359c2c66affSColin Finck return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
360c2c66affSColin Finck case IOCTL_GETCONTROLDETAILS:
361c2c66affSColin Finck return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
362c2c66affSColin Finck case IOCTL_QUERYDEVICEINTERFACESTRING:
363c2c66affSColin Finck return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
364c2c66affSColin Finck case IOCTL_GET_MIXER_EVENT:
365c2c66affSColin Finck return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
366c2c66affSColin Finck case IOCTL_RESET_STREAM:
367c2c66affSColin Finck return WdmAudResetStream(DeviceObject, Irp, DeviceInfo);
368c2c66affSColin Finck case IOCTL_GETPOS:
369*d1b8feb6SOleg Dubinskiy return WdmAudGetPosition(DeviceObject, Irp, DeviceInfo);
370c2c66affSColin Finck case IOCTL_GETDEVID:
371c2c66affSColin Finck case IOCTL_GETVOLUME:
372c2c66affSColin Finck case IOCTL_SETVOLUME:
373c2c66affSColin Finck
374c2c66affSColin Finck DPRINT1("Unhandled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
375c2c66affSColin Finck break;
376c2c66affSColin Finck }
377c2c66affSColin Finck
378c2c66affSColin Finck return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
379c2c66affSColin Finck }
380c2c66affSColin Finck
381c2c66affSColin Finck NTSTATUS
382c2c66affSColin Finck NTAPI
IoCompletion(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Ctx)383c2c66affSColin Finck IoCompletion (
384c2c66affSColin Finck PDEVICE_OBJECT DeviceObject,
385c2c66affSColin Finck PIRP Irp,
386c2c66affSColin Finck PVOID Ctx)
387c2c66affSColin Finck {
388c2c66affSColin Finck PKSSTREAM_HEADER Header;
389c2c66affSColin Finck PMDL Mdl, NextMdl;
390c2c66affSColin Finck PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx;
391c2c66affSColin Finck
392c2c66affSColin Finck /* get stream header */
393c2c66affSColin Finck Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
394c2c66affSColin Finck
395c2c66affSColin Finck /* sanity check */
396c2c66affSColin Finck ASSERT(Header);
397c2c66affSColin Finck
398c2c66affSColin Finck /* time to free all allocated mdls */
399c2c66affSColin Finck Mdl = Irp->MdlAddress;
400c2c66affSColin Finck
401c2c66affSColin Finck while(Mdl)
402c2c66affSColin Finck {
403c2c66affSColin Finck /* get next mdl */
404c2c66affSColin Finck NextMdl = Mdl->Next;
405c2c66affSColin Finck
406c2c66affSColin Finck /* unlock pages */
407c2c66affSColin Finck MmUnlockPages(Mdl);
408c2c66affSColin Finck
409c2c66affSColin Finck /* grab next mdl */
410c2c66affSColin Finck Mdl = NextMdl;
411c2c66affSColin Finck }
412c2c66affSColin Finck //IoFreeMdl(Mdl);
413c2c66affSColin Finck /* clear mdl list */
414c2c66affSColin Finck Irp->MdlAddress = Context->Mdl;
415c2c66affSColin Finck
416c2c66affSColin Finck
417c2c66affSColin Finck
418c2c66affSColin Finck DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
419c2c66affSColin Finck
420c2c66affSColin Finck if (!NT_SUCCESS(Irp->IoStatus.Status))
421c2c66affSColin Finck {
422c2c66affSColin Finck /* failed */
423c2c66affSColin Finck Irp->IoStatus.Information = 0;
424c2c66affSColin Finck }
425c2c66affSColin Finck
426c2c66affSColin Finck /* dereference file object */
427c2c66affSColin Finck ObDereferenceObject(Context->FileObject);
428c2c66affSColin Finck
429c2c66affSColin Finck /* free context */
430c2c66affSColin Finck FreeItem(Context);
431c2c66affSColin Finck
432c2c66affSColin Finck return STATUS_SUCCESS;
433c2c66affSColin Finck }
434c2c66affSColin Finck
435c2c66affSColin Finck NTSTATUS
436c2c66affSColin Finck NTAPI
WdmAudReadWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)437c2c66affSColin Finck WdmAudReadWrite(
438c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
439c2c66affSColin Finck IN PIRP Irp)
440c2c66affSColin Finck {
441c2c66affSColin Finck NTSTATUS Status;
442c2c66affSColin Finck PWDMAUD_DEVICE_INFO DeviceInfo;
443c2c66affSColin Finck PFILE_OBJECT FileObject;
444c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
445c2c66affSColin Finck ULONG Length;
446c2c66affSColin Finck PMDL Mdl;
447c2c66affSColin Finck BOOLEAN Read = TRUE;
448c2c66affSColin Finck PWDMAUD_COMPLETION_CONTEXT Context;
449c2c66affSColin Finck
450c2c66affSColin Finck /* allocate completion context */
451c2c66affSColin Finck Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT));
452c2c66affSColin Finck
453c2c66affSColin Finck if (!Context)
454c2c66affSColin Finck {
455c2c66affSColin Finck /* not enough memory */
456c2c66affSColin Finck Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
457c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
458c2c66affSColin Finck
459c2c66affSColin Finck /* done */
460c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
461c2c66affSColin Finck }
462c2c66affSColin Finck
463c2c66affSColin Finck /* get current irp stack location */
464c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp);
465c2c66affSColin Finck
466c2c66affSColin Finck /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
467c2c66affSColin Finck Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
468c2c66affSColin Finck
469c2c66affSColin Finck /* sanity check */
470c2c66affSColin Finck ASSERT(Irp->UserBuffer);
471c2c66affSColin Finck
472c2c66affSColin Finck /* get the length of the request length */
473c2c66affSColin Finck Length = IoStack->Parameters.Write.Length;
474c2c66affSColin Finck
475c2c66affSColin Finck /* store outputbuffer length */
476c2c66affSColin Finck IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
477c2c66affSColin Finck
478c2c66affSColin Finck /* setup context */
479c2c66affSColin Finck Context->Length = Length;
480c2c66affSColin Finck Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
481c2c66affSColin Finck Context->Mdl = Irp->MdlAddress;
482c2c66affSColin Finck
483c2c66affSColin Finck /* store mdl address */
484c2c66affSColin Finck Mdl = Irp->MdlAddress;
485c2c66affSColin Finck
486c2c66affSColin Finck /* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */
487c2c66affSColin Finck Irp->MdlAddress = NULL;
488c2c66affSColin Finck
489c2c66affSColin Finck if (IoStack->MajorFunction == IRP_MJ_WRITE)
490c2c66affSColin Finck {
491c2c66affSColin Finck /* probe the write stream irp */
492c2c66affSColin Finck Read = FALSE;
493c2c66affSColin Finck Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
494c2c66affSColin Finck }
495c2c66affSColin Finck else
496c2c66affSColin Finck {
497c2c66affSColin Finck /* probe the read stream irp */
498c2c66affSColin Finck Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
499c2c66affSColin Finck }
500c2c66affSColin Finck
501c2c66affSColin Finck if (!NT_SUCCESS(Status))
502c2c66affSColin Finck {
503c2c66affSColin Finck DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
504c2c66affSColin Finck Irp->MdlAddress = Mdl;
505c2c66affSColin Finck FreeItem(Context);
506c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, 0);
507c2c66affSColin Finck }
508c2c66affSColin Finck
509c2c66affSColin Finck /* get device info */
510c2c66affSColin Finck DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
511c2c66affSColin Finck ASSERT(DeviceInfo);
512c2c66affSColin Finck
513c2c66affSColin Finck /* now get sysaudio file object */
514c2c66affSColin Finck Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
515c2c66affSColin Finck if (!NT_SUCCESS(Status))
516c2c66affSColin Finck {
517c2c66affSColin Finck DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
518c2c66affSColin Finck Irp->MdlAddress = Mdl;
519c2c66affSColin Finck FreeItem(Context);
520c2c66affSColin Finck return SetIrpIoStatus(Irp, Status, 0);
521c2c66affSColin Finck }
522c2c66affSColin Finck
523c2c66affSColin Finck /* store file object whose reference is released in the completion callback */
524c2c66affSColin Finck Context->FileObject = FileObject;
525c2c66affSColin Finck
526c2c66affSColin Finck /* skip current irp stack location */
527c2c66affSColin Finck IoSkipCurrentIrpStackLocation(Irp);
528c2c66affSColin Finck
529c2c66affSColin Finck /* get next stack location */
530c2c66affSColin Finck IoStack = IoGetNextIrpStackLocation(Irp);
531c2c66affSColin Finck
532c2c66affSColin Finck /* prepare stack location */
533c2c66affSColin Finck IoStack->FileObject = FileObject;
534c2c66affSColin Finck IoStack->Parameters.Write.Length = Length;
535c2c66affSColin Finck IoStack->MajorFunction = IRP_MJ_WRITE;
536c2c66affSColin Finck IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
537c2c66affSColin Finck IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
538c2c66affSColin Finck
539c2c66affSColin Finck /* mark irp as pending */
540c2c66affSColin Finck // IoMarkIrpPending(Irp);
541c2c66affSColin Finck /* call the driver */
542c2c66affSColin Finck Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
543c2c66affSColin Finck return Status;
544c2c66affSColin Finck }
545