[KS]
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / filter_wavecyclic.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c
5 * PURPOSE: portcls wave cyclic filter
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.h"
10
11 typedef struct
12 {
13 IPortFilterWaveCyclicVtbl *lpVtbl;
14
15 LONG ref;
16
17 IPortWaveCyclic* Port;
18 IPortPinWaveCyclic ** Pins;
19 SUBDEVICE_DESCRIPTOR * Descriptor;
20 ISubdevice * SubDevice;
21
22 }IPortFilterWaveCyclicImpl;
23
24 /*
25 * @implemented
26 */
27 NTSTATUS
28 NTAPI
29 IPortFilterWaveCyclic_fnQueryInterface(
30 IPortFilterWaveCyclic* iface,
31 IN REFIID refiid,
32 OUT PVOID* Output)
33 {
34 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
35
36 if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
37 IsEqualGUIDAligned(refiid, &IID_IUnknown))
38 {
39 *Output = &This->lpVtbl;
40 InterlockedIncrement(&This->ref);
41 return STATUS_SUCCESS;
42 }
43 else if (IsEqualGUIDAligned(refiid, &IID_IPort))
44 {
45 *Output = This->Port;
46 This->Port->lpVtbl->AddRef(This->Port);
47 return STATUS_SUCCESS;
48 }
49
50
51 return STATUS_UNSUCCESSFUL;
52 }
53
54 /*
55 * @implemented
56 */
57 ULONG
58 NTAPI
59 IPortFilterWaveCyclic_fnAddRef(
60 IPortFilterWaveCyclic* iface)
61 {
62 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
63
64 return InterlockedIncrement(&This->ref);
65 }
66
67 /*
68 * @implemented
69 */
70 ULONG
71 NTAPI
72 IPortFilterWaveCyclic_fnRelease(
73 IPortFilterWaveCyclic* iface)
74 {
75 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
76
77 InterlockedDecrement(&This->ref);
78
79 if (This->ref == 0)
80 {
81 FreeItem(This, TAG_PORTCLASS);
82 return 0;
83 }
84 return This->ref;
85 }
86
87 /*
88 * @implemented
89 */
90 NTSTATUS
91 NTAPI
92 IPortFilterWaveCyclic_fnNewIrpTarget(
93 IN IPortFilterWaveCyclic* iface,
94 OUT struct IIrpTarget **OutTarget,
95 IN WCHAR * Name,
96 IN PUNKNOWN Unknown,
97 IN POOL_TYPE PoolType,
98 IN PDEVICE_OBJECT DeviceObject,
99 IN PIRP Irp,
100 IN KSOBJECT_CREATE *CreateObject)
101 {
102 NTSTATUS Status;
103 IPortPinWaveCyclic * Pin;
104 PKSPIN_CONNECT ConnectDetails;
105 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
106
107 ASSERT(This->Port);
108 ASSERT(This->Descriptor);
109 ASSERT(This->Pins);
110
111 DPRINT("IPortFilterWaveCyclic_fnNewIrpTarget entered\n");
112
113 /* let's verify the connection request */
114 Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
115 if (!NT_SUCCESS(Status))
116 {
117 return STATUS_UNSUCCESSFUL;
118 }
119
120 if (This->Pins[ConnectDetails->PinId] &&
121 (This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == This->Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
122 {
123 /* release existing instance */
124 return STATUS_UNSUCCESSFUL;
125 }
126
127 /* now create the pin */
128 Status = NewPortPinWaveCyclic(&Pin);
129 if (!NT_SUCCESS(Status))
130 {
131 return Status;
132 }
133
134 /* initialize the pin */
135 Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId]);
136 if (!NT_SUCCESS(Status))
137 {
138 Pin->lpVtbl->Release(Pin);
139 return Status;
140 }
141
142 /* store pin */
143 This->Pins[ConnectDetails->PinId] = Pin;
144
145 /* store result */
146 *OutTarget = (IIrpTarget*)Pin;
147
148 /* increment current instance count */
149 This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
150
151 return Status;
152 }
153
154 /*
155 * @implemented
156 */
157 NTSTATUS
158 NTAPI
159 IPortFilterWaveCyclic_fnDeviceIoControl(
160 IN IPortFilterWaveCyclic* iface,
161 IN PDEVICE_OBJECT DeviceObject,
162 IN PIRP Irp)
163 {
164 PIO_STACK_LOCATION IoStack;
165 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
166
167 IoStack = IoGetCurrentIrpStackLocation(Irp);
168
169 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
170 {
171 DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
172
173 Irp->IoStatus.Status = STATUS_SUCCESS;
174
175 IoCompleteRequest(Irp, IO_NO_INCREMENT);
176 return STATUS_SUCCESS;
177 }
178
179
180 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
181
182 return PcPropertyHandler(Irp, This->Descriptor);
183 }
184
185 /*
186 * @implemented
187 */
188 NTSTATUS
189 NTAPI
190 IPortFilterWaveCyclic_fnRead(
191 IN IPortFilterWaveCyclic* iface,
192 IN PDEVICE_OBJECT DeviceObject,
193 IN PIRP Irp)
194 {
195 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
196 }
197
198 /*
199 * @implemented
200 */
201 NTSTATUS
202 NTAPI
203 IPortFilterWaveCyclic_fnWrite(
204 IN IPortFilterWaveCyclic* iface,
205 IN PDEVICE_OBJECT DeviceObject,
206 IN PIRP Irp)
207 {
208 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
209 }
210
211 /*
212 * @implemented
213 */
214 NTSTATUS
215 NTAPI
216 IPortFilterWaveCyclic_fnFlush(
217 IN IPortFilterWaveCyclic* iface,
218 IN PDEVICE_OBJECT DeviceObject,
219 IN PIRP Irp)
220 {
221 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
222 }
223
224 /*
225 * @implemented
226 */
227 NTSTATUS
228 NTAPI
229 IPortFilterWaveCyclic_fnClose(
230 IN IPortFilterWaveCyclic* iface,
231 IN PDEVICE_OBJECT DeviceObject,
232 IN PIRP Irp)
233 {
234 ULONG Index;
235 NTSTATUS Status = STATUS_SUCCESS;
236 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
237
238 for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
239 {
240 /* all pins should have been closed by now */
241 ASSERT(This->Pins[Index] == NULL);
242 }
243
244 DPRINT("IPortFilterWaveCyclic_fnClose ref %u\n", This->ref);
245
246 if (This->ref == 1)
247 {
248 /* release reference to port */
249 This->SubDevice->lpVtbl->Release(This->SubDevice);
250
251 /* time to shutdown the audio system */
252 Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice);
253 }
254
255 Irp->IoStatus.Status = Status;
256 Irp->IoStatus.Information = 0;
257 IoCompleteRequest(Irp, IO_NO_INCREMENT);
258
259 return STATUS_SUCCESS;
260 }
261
262 /*
263 * @implemented
264 */
265 NTSTATUS
266 NTAPI
267 IPortFilterWaveCyclic_fnQuerySecurity(
268 IN IPortFilterWaveCyclic* iface,
269 IN PDEVICE_OBJECT DeviceObject,
270 IN PIRP Irp)
271 {
272 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
273 }
274
275 /*
276 * @implemented
277 */
278 NTSTATUS
279 NTAPI
280 IPortFilterWaveCyclic_fnSetSecurity(
281 IN IPortFilterWaveCyclic* iface,
282 IN PDEVICE_OBJECT DeviceObject,
283 IN PIRP Irp)
284 {
285 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
286 }
287
288 /*
289 * @implemented
290 */
291 BOOLEAN
292 NTAPI
293 IPortFilterWaveCyclic_fnFastDeviceIoControl(
294 IN IPortFilterWaveCyclic* iface,
295 IN PFILE_OBJECT FileObject,
296 IN BOOLEAN Wait,
297 IN PVOID InputBuffer,
298 IN ULONG InputBufferLength,
299 OUT PVOID OutputBuffer,
300 IN ULONG OutputBufferLength,
301 IN ULONG IoControlCode,
302 OUT PIO_STATUS_BLOCK StatusBlock,
303 IN PDEVICE_OBJECT DeviceObject)
304 {
305 UNIMPLEMENTED
306 return FALSE;
307 }
308
309 /*
310 * @implemented
311 */
312 BOOLEAN
313 NTAPI
314 IPortFilterWaveCyclic_fnFastRead(
315 IN IPortFilterWaveCyclic* iface,
316 IN PFILE_OBJECT FileObject,
317 IN PLARGE_INTEGER FileOffset,
318 IN ULONG Length,
319 IN BOOLEAN Wait,
320 IN ULONG LockKey,
321 IN PVOID Buffer,
322 OUT PIO_STATUS_BLOCK StatusBlock,
323 IN PDEVICE_OBJECT DeviceObject)
324 {
325 UNIMPLEMENTED
326 return FALSE;
327 }
328
329 /*
330 * @implemented
331 */
332 BOOLEAN
333 NTAPI
334 IPortFilterWaveCyclic_fnFastWrite(
335 IN IPortFilterWaveCyclic* iface,
336 IN PFILE_OBJECT FileObject,
337 IN PLARGE_INTEGER FileOffset,
338 IN ULONG Length,
339 IN BOOLEAN Wait,
340 IN ULONG LockKey,
341 IN PVOID Buffer,
342 OUT PIO_STATUS_BLOCK StatusBlock,
343 IN PDEVICE_OBJECT DeviceObject)
344 {
345 UNIMPLEMENTED
346 return FALSE;
347 }
348
349 /*
350 * @implemented
351 */
352 static
353 NTSTATUS
354 NTAPI
355 IPortFilterWaveCyclic_fnInit(
356 IN IPortFilterWaveCyclic* iface,
357 IN IPortWaveCyclic* Port)
358 {
359 ISubdevice * ISubDevice;
360 SUBDEVICE_DESCRIPTOR * Descriptor;
361 NTSTATUS Status;
362 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
363
364 /* get our private interface */
365 Status = Port->lpVtbl->QueryInterface(Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
366 if (!NT_SUCCESS(Status))
367 return STATUS_UNSUCCESSFUL;
368
369 /* get the subdevice descriptor */
370 Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
371
372 /* store subdevice interface */
373 This->SubDevice = ISubDevice;
374
375 if (!NT_SUCCESS(Status))
376 return STATUS_UNSUCCESSFUL;
377
378 /* save descriptor */
379 This->Descriptor = Descriptor;
380
381 /* allocate pin array */
382 This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveCyclic*), TAG_PORTCLASS);
383
384 if (!This->Pins)
385 return STATUS_UNSUCCESSFUL;
386
387 /* store port driver */
388 This->Port = Port;
389
390 return STATUS_SUCCESS;
391 }
392
393
394 static
395 NTSTATUS
396 NTAPI
397 IPortFilterWaveCyclic_fnFreePin(
398 IN IPortFilterWaveCyclic* iface,
399 IN struct IPortPinWaveCyclic* Pin)
400 {
401 ULONG Index;
402 IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
403
404 for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
405 {
406 if (This->Pins[Index] == Pin)
407 {
408 This->Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
409 This->Pins[Index]->lpVtbl->Release(This->Pins[Index]);
410 This->Pins[Index] = NULL;
411 return STATUS_SUCCESS;
412 }
413 }
414 return STATUS_UNSUCCESSFUL;
415 }
416
417 static IPortFilterWaveCyclicVtbl vt_IPortFilterWaveCyclic =
418 {
419 IPortFilterWaveCyclic_fnQueryInterface,
420 IPortFilterWaveCyclic_fnAddRef,
421 IPortFilterWaveCyclic_fnRelease,
422 IPortFilterWaveCyclic_fnNewIrpTarget,
423 IPortFilterWaveCyclic_fnDeviceIoControl,
424 IPortFilterWaveCyclic_fnRead,
425 IPortFilterWaveCyclic_fnWrite,
426 IPortFilterWaveCyclic_fnFlush,
427 IPortFilterWaveCyclic_fnClose,
428 IPortFilterWaveCyclic_fnQuerySecurity,
429 IPortFilterWaveCyclic_fnSetSecurity,
430 IPortFilterWaveCyclic_fnFastDeviceIoControl,
431 IPortFilterWaveCyclic_fnFastRead,
432 IPortFilterWaveCyclic_fnFastWrite,
433 IPortFilterWaveCyclic_fnInit,
434 IPortFilterWaveCyclic_fnFreePin
435 };
436
437 NTSTATUS
438 NewPortFilterWaveCyclic(
439 OUT IPortFilterWaveCyclic ** OutFilter)
440 {
441 IPortFilterWaveCyclicImpl * This;
442
443 This = AllocateItem(NonPagedPool, sizeof(IPortFilterWaveCyclicImpl), TAG_PORTCLASS);
444 if (!This)
445 return STATUS_INSUFFICIENT_RESOURCES;
446
447 /* initialize IPortFilterWaveCyclic */
448 This->ref = 1;
449 This->lpVtbl = &vt_IPortFilterWaveCyclic;
450
451 /* return result */
452 *OutFilter = (IPortFilterWaveCyclic*)&This->lpVtbl;
453
454 return STATUS_SUCCESS;
455 }
456
457