Sync to trunk head (r42241)
[reactos.git] / reactos / drivers / wdm / audio / sysaudio / pin.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/deviface.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "sysaudio.h"
10
11 NTSTATUS
12 NTAPI
13 Pin_fnDeviceIoControl(
14 PDEVICE_OBJECT DeviceObject,
15 PIRP Irp)
16 {
17 PDISPATCH_CONTEXT Context;
18 NTSTATUS Status;
19 ULONG BytesReturned;
20 PFILE_OBJECT FileObject;
21 PIO_STACK_LOCATION IoStack;
22
23 DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
24
25 /* Get current stack location */
26 IoStack = IoGetCurrentIrpStackLocation(Irp);
27
28 /* The dispatch context is stored in the FsContext2 member */
29 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
30
31 /* Sanity check */
32 ASSERT(Context);
33
34 /* acquire real pin file object */
35 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
36 if (!NT_SUCCESS(Status))
37 {
38 Irp->IoStatus.Information = 0;
39 Irp->IoStatus.Status = Status;
40 /* Complete the irp */
41 IoCompleteRequest(Irp, IO_NO_INCREMENT);
42 return Status;
43 }
44
45 /* Re-dispatch the request to the real target pin */
46 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
47 IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
48 IoStack->Parameters.DeviceIoControl.InputBufferLength,
49 Irp->UserBuffer,
50 IoStack->Parameters.DeviceIoControl.OutputBufferLength,
51 &BytesReturned);
52 /* release file object */
53 ObDereferenceObject(FileObject);
54
55 /* Save status and information */
56 Irp->IoStatus.Information = BytesReturned;
57 Irp->IoStatus.Status = Status;
58 /* Complete the irp */
59 IoCompleteRequest(Irp, IO_NO_INCREMENT);
60 /* Done */
61 return Status;
62 }
63
64 NTSTATUS
65 NTAPI
66 Pin_fnRead(
67 PDEVICE_OBJECT DeviceObject,
68 PIRP Irp)
69 {
70 PDISPATCH_CONTEXT Context;
71 PIO_STACK_LOCATION IoStack;
72 ULONG BytesReturned;
73 PFILE_OBJECT FileObject;
74 NTSTATUS Status;
75
76 /* Get current stack location */
77 IoStack = IoGetCurrentIrpStackLocation(Irp);
78
79 /* The dispatch context is stored in the FsContext2 member */
80 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
81
82 /* Sanity check */
83 ASSERT(Context);
84
85 /* acquire real pin file object */
86 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
87 if (!NT_SUCCESS(Status))
88 {
89 Irp->IoStatus.Information = 0;
90 Irp->IoStatus.Status = Status;
91 /* Complete the irp */
92 IoCompleteRequest(Irp, IO_NO_INCREMENT);
93 return Status;
94 }
95
96 /* Re-dispatch the request to the real target pin */
97 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_READ_STREAM,
98 MmGetMdlVirtualAddress(Irp->MdlAddress),
99 IoStack->Parameters.Read.Length,
100 NULL,
101 0,
102 &BytesReturned);
103
104 /* release file object */
105 ObDereferenceObject(FileObject);
106
107 if (Context->hMixerPin)
108 {
109 // FIXME
110 // call kmixer to convert stream
111 UNIMPLEMENTED
112 }
113
114 /* Save status and information */
115 Irp->IoStatus.Status = Status;
116 Irp->IoStatus.Information = 0;
117 /* Complete the irp */
118 IoCompleteRequest(Irp, IO_NO_INCREMENT);
119 /* Done */
120 return Status;
121 }
122
123 NTSTATUS
124 NTAPI
125 Pin_fnWrite(
126 PDEVICE_OBJECT DeviceObject,
127 PIRP Irp)
128 {
129 PDISPATCH_CONTEXT Context;
130 PIO_STACK_LOCATION IoStack;
131 PFILE_OBJECT FileObject;
132 NTSTATUS Status;
133 ULONG BytesReturned;
134
135 /* Get current stack location */
136 IoStack = IoGetCurrentIrpStackLocation(Irp);
137
138 /* The dispatch context is stored in the FsContext2 member */
139 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
140
141 /* Sanity check */
142 ASSERT(Context);
143
144 if (Context->hMixerPin)
145 {
146 // FIXME
147 // call kmixer to convert stream
148 UNIMPLEMENTED
149 }
150
151 /* acquire real pin file object */
152 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
153 if (!NT_SUCCESS(Status))
154 {
155 Irp->IoStatus.Information = 0;
156 Irp->IoStatus.Status = Status;
157 /* Complete the irp */
158 IoCompleteRequest(Irp, IO_NO_INCREMENT);
159 return Status;
160 }
161
162 /* call the portcls audio pin */
163 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
164 MmGetMdlVirtualAddress(Irp->MdlAddress),
165 IoStack->Parameters.Write.Length,
166 NULL,
167 0,
168 &BytesReturned);
169
170
171 /* Release file object */
172 ObDereferenceObject(FileObject);
173
174 /* Save status and information */
175 Irp->IoStatus.Status = Status;
176 Irp->IoStatus.Information = BytesReturned;
177 /* Complete the irp */
178 IoCompleteRequest(Irp, IO_NO_INCREMENT);
179 /* Done */
180 return Status;
181 }
182
183 NTSTATUS
184 NTAPI
185 Pin_fnFlush(
186 PDEVICE_OBJECT DeviceObject,
187 PIRP Irp)
188 {
189 PDISPATCH_CONTEXT Context;
190 PIO_STACK_LOCATION IoStack;
191 PDEVICE_OBJECT PinDeviceObject;
192 PIRP PinIrp;
193 PFILE_OBJECT FileObject;
194 IO_STATUS_BLOCK IoStatus;
195 KEVENT Event;
196 NTSTATUS Status = STATUS_UNSUCCESSFUL;
197
198 /* Get current stack location */
199 IoStack = IoGetCurrentIrpStackLocation(Irp);
200
201 /* The dispatch context is stored in the FsContext2 member */
202 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
203
204 /* Sanity check */
205 ASSERT(Context);
206
207
208 /* acquire real pin file object */
209 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
210 if (!NT_SUCCESS(Status))
211 {
212 Irp->IoStatus.Information = 0;
213 Irp->IoStatus.Status = Status;
214 /* Complete the irp */
215 IoCompleteRequest(Irp, IO_NO_INCREMENT);
216 return Status;
217 }
218
219 /* Get Pin's device object */
220 PinDeviceObject = IoGetRelatedDeviceObject(FileObject);
221
222 /* release file object */
223 ObDereferenceObject(FileObject);
224
225 /* Initialize notification event */
226 KeInitializeEvent(&Event, NotificationEvent, FALSE);
227
228 /* build target irp */
229 PinIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, PinDeviceObject, NULL, 0, NULL, &Event, &IoStatus);
230 if (PinIrp)
231 {
232
233 /* Get the next stack location */
234 IoStack = IoGetNextIrpStackLocation(PinIrp);
235 /* The file object must be present in the irp as it contains the KSOBJECT_HEADER */
236 IoStack->FileObject = FileObject;
237
238 /* call the driver */
239 Status = IoCallDriver(PinDeviceObject, PinIrp);
240 /* Has request already completed ? */
241 if (Status == STATUS_PENDING)
242 {
243 /* Wait untill the request has completed */
244 KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
245 /* Update status */
246 Status = IoStatus.Status;
247 }
248 }
249
250 /* store status */
251 Irp->IoStatus.Status = Status;
252 Irp->IoStatus.Information = 0;
253 /* Complete the irp */
254 IoCompleteRequest(Irp, IO_NO_INCREMENT);
255 /* Done */
256 return Status;
257 }
258
259 NTSTATUS
260 NTAPI
261 Pin_fnClose(
262 PDEVICE_OBJECT DeviceObject,
263 PIRP Irp)
264 {
265 PDISPATCH_CONTEXT Context;
266 PIO_STACK_LOCATION IoStack;
267
268 DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
269
270 /* Get current stack location */
271 IoStack = IoGetCurrentIrpStackLocation(Irp);
272
273 /* The dispatch context is stored in the FsContext2 member */
274 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
275
276 if (Context->Handle)
277 {
278 ZwClose(Context->Handle);
279 }
280 ZwClose(Context->hMixerPin);
281
282 ExFreePool(Context);
283
284 Irp->IoStatus.Status = STATUS_SUCCESS;
285 Irp->IoStatus.Information = 0;
286 IoCompleteRequest(Irp, IO_NO_INCREMENT);
287 return STATUS_SUCCESS;
288 }
289
290 NTSTATUS
291 NTAPI
292 Pin_fnQuerySecurity(
293 PDEVICE_OBJECT DeviceObject,
294 PIRP Irp)
295 {
296 DPRINT("Pin_fnQuerySecurity called DeviceObject %p Irp %p\n", DeviceObject);
297
298 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
299 Irp->IoStatus.Information = 0;
300 IoCompleteRequest(Irp, IO_NO_INCREMENT);
301 return STATUS_UNSUCCESSFUL;
302 }
303
304 NTSTATUS
305 NTAPI
306 Pin_fnSetSecurity(
307 PDEVICE_OBJECT DeviceObject,
308 PIRP Irp)
309 {
310
311 DPRINT("Pin_fnSetSecurity called DeviceObject %p Irp %p\n", DeviceObject);
312
313 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
314 Irp->IoStatus.Information = 0;
315 IoCompleteRequest(Irp, IO_NO_INCREMENT);
316 return STATUS_UNSUCCESSFUL;
317 }
318
319 BOOLEAN
320 NTAPI
321 Pin_fnFastDeviceIoControl(
322 PFILE_OBJECT FileObject,
323 BOOLEAN Wait,
324 PVOID InputBuffer,
325 ULONG InputBufferLength,
326 PVOID OutputBuffer,
327 ULONG OutputBufferLength,
328 ULONG IoControlCode,
329 PIO_STATUS_BLOCK IoStatus,
330 PDEVICE_OBJECT DeviceObject)
331 {
332 DPRINT("Pin_fnFastDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
333
334
335 return FALSE;
336 }
337
338
339 BOOLEAN
340 NTAPI
341 Pin_fnFastRead(
342 PFILE_OBJECT FileObject,
343 PLARGE_INTEGER FileOffset,
344 ULONG Length,
345 BOOLEAN Wait,
346 ULONG LockKey,
347 PVOID Buffer,
348 PIO_STATUS_BLOCK IoStatus,
349 PDEVICE_OBJECT DeviceObject)
350 {
351 DPRINT("Pin_fnFastRead called DeviceObject %p Irp %p\n", DeviceObject);
352
353 return FALSE;
354
355 }
356
357 BOOLEAN
358 NTAPI
359 Pin_fnFastWrite(
360 PFILE_OBJECT FileObject,
361 PLARGE_INTEGER FileOffset,
362 ULONG Length,
363 BOOLEAN Wait,
364 ULONG LockKey,
365 PVOID Buffer,
366 PIO_STATUS_BLOCK IoStatus,
367 PDEVICE_OBJECT DeviceObject)
368 {
369 PDISPATCH_CONTEXT Context;
370 PFILE_OBJECT RealFileObject;
371 NTSTATUS Status;
372
373 DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
374
375 Context = (PDISPATCH_CONTEXT)FileObject->FsContext2;
376
377 if (Context->hMixerPin)
378 {
379 Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
380 if (NT_SUCCESS(Status))
381 {
382 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
383 ObDereferenceObject(RealFileObject);
384 }
385
386 if (!NT_SUCCESS(Status))
387 {
388 DPRINT1("Mixing stream failed with %lx\n", Status);
389 return FALSE;
390 }
391 }
392
393 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
394 if (!NT_SUCCESS(Status))
395 return FALSE;
396
397 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
398
399 ObDereferenceObject(RealFileObject);
400
401 if (Status == STATUS_SUCCESS)
402 return TRUE;
403 else
404 return FALSE;
405 }
406
407 static KSDISPATCH_TABLE PinTable =
408 {
409 Pin_fnDeviceIoControl,
410 Pin_fnRead,
411 Pin_fnWrite,
412 Pin_fnFlush,
413 Pin_fnClose,
414 Pin_fnQuerySecurity,
415 Pin_fnSetSecurity,
416 Pin_fnFastDeviceIoControl,
417 Pin_fnFastRead,
418 Pin_fnFastWrite,
419 };
420
421 NTSTATUS
422 CreateSysAudioPin(
423 IN PIRP Irp)
424 {
425 NTSTATUS Status;
426 KSOBJECT_HEADER ObjectHeader;
427
428 /* allocate object header */
429 Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
430 return Status;
431 }