80a8d2b84bd49c02f664162ef65b99c180208208
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / filter_wavecyclic.cpp
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.hpp"
10
11 class CPortFilterWaveCyclic : public IPortFilterWaveCyclic
12 {
13 public:
14 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
15
16 STDMETHODIMP_(ULONG) AddRef()
17 {
18 InterlockedIncrement(&m_Ref);
19 return m_Ref;
20 }
21 STDMETHODIMP_(ULONG) Release()
22 {
23 InterlockedDecrement(&m_Ref);
24
25 if (!m_Ref)
26 {
27 delete this;
28 return 0;
29 }
30 return m_Ref;
31 }
32 IMP_IPortFilterWaveCyclic;
33 CPortFilterWaveCyclic(IUnknown *OuterUnknown){}
34 virtual ~CPortFilterWaveCyclic(){}
35
36 protected:
37 IPortWaveCyclic* m_Port;
38 IPortPinWaveCyclic ** m_Pins;
39 SUBDEVICE_DESCRIPTOR * m_Descriptor;
40 ISubdevice * m_SubDevice;
41 LONG m_Ref;
42 };
43
44 NTSTATUS
45 NTAPI
46 CPortFilterWaveCyclic::QueryInterface(
47 IN REFIID refiid,
48 OUT PVOID* Output)
49 {
50 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
51 IsEqualGUIDAligned(refiid, IID_IUnknown))
52 {
53 *Output = PVOID(PUNKNOWN(this));
54 PUNKNOWN(*Output)->AddRef();
55 return STATUS_SUCCESS;
56 }
57 else if (IsEqualGUIDAligned(refiid, IID_IPort))
58 {
59 *Output = PUNKNOWN(m_Port);
60 PUNKNOWN(*Output)->AddRef();
61 return STATUS_SUCCESS;
62 }
63
64 return STATUS_UNSUCCESSFUL;
65 }
66
67 NTSTATUS
68 NTAPI
69 CPortFilterWaveCyclic::NewIrpTarget(
70 OUT struct IIrpTarget **OutTarget,
71 IN WCHAR * Name,
72 IN PUNKNOWN Unknown,
73 IN POOL_TYPE PoolType,
74 IN PDEVICE_OBJECT DeviceObject,
75 IN PIRP Irp,
76 IN KSOBJECT_CREATE *CreateObject)
77 {
78 NTSTATUS Status;
79 IPortPinWaveCyclic * Pin;
80 PKSPIN_CONNECT ConnectDetails;
81
82 #if 0
83 ASSERT(m_Port);
84 ASSERT(m_Descriptor);
85 ASSERT(m_Pins);
86 #endif
87
88 DPRINT("CPortFilterWaveCyclic::NewIrpTarget entered\n");
89
90 // let's verify the connection request
91 Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
92 if (!NT_SUCCESS(Status))
93 {
94 return STATUS_UNSUCCESSFUL;
95 }
96
97 if (m_Pins[ConnectDetails->PinId] &&
98 (m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
99 {
100 // release existing instance
101 return STATUS_UNSUCCESSFUL;
102 }
103
104 // now create the pin
105 Status = NewPortPinWaveCyclic(&Pin);
106 if (!NT_SUCCESS(Status))
107 {
108 return Status;
109 }
110
111 // initialize the pin
112 Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId]);
113 if (!NT_SUCCESS(Status))
114 {
115 Pin->Release();
116 return Status;
117 }
118
119 // store pin
120 m_Pins[ConnectDetails->PinId] = Pin;
121
122 // store result
123 *OutTarget = (IIrpTarget*)Pin;
124
125 // increment current instance count
126 m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
127
128 return Status;
129 }
130
131 NTSTATUS
132 NTAPI
133 CPortFilterWaveCyclic::DeviceIoControl(
134 IN PDEVICE_OBJECT DeviceObject,
135 IN PIRP Irp)
136 {
137 PIO_STACK_LOCATION IoStack;
138
139 IoStack = IoGetCurrentIrpStackLocation(Irp);
140
141 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
142 {
143 DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
144
145 Irp->IoStatus.Status = STATUS_SUCCESS;
146
147 IoCompleteRequest(Irp, IO_NO_INCREMENT);
148 return STATUS_SUCCESS;
149 }
150
151 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
152
153 return PcPropertyHandler(Irp, m_Descriptor);
154 }
155
156 NTSTATUS
157 NTAPI
158 CPortFilterWaveCyclic::Read(
159 IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp)
161 {
162 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
163 }
164
165 NTSTATUS
166 NTAPI
167 CPortFilterWaveCyclic::Write(
168 IN PDEVICE_OBJECT DeviceObject,
169 IN PIRP Irp)
170 {
171 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
172 }
173
174 NTSTATUS
175 NTAPI
176 CPortFilterWaveCyclic::Flush(
177 IN PDEVICE_OBJECT DeviceObject,
178 IN PIRP Irp)
179 {
180 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
181 }
182
183 NTSTATUS
184 NTAPI
185 CPortFilterWaveCyclic::Close(
186 IN PDEVICE_OBJECT DeviceObject,
187 IN PIRP Irp)
188 {
189 //ULONG Index;
190 NTSTATUS Status = STATUS_SUCCESS;
191
192 #if 0
193 if (m_ref == 1)
194 {
195 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
196 {
197 // all pins should have been closed by now
198 ASSERT(m_Pins[Index] == NULL);
199 }
200
201 // release reference to port
202 m_SubDevice->Release(m_SubDevice);
203
204 // time to shutdown the audio system
205 Status = m_SubDevice->ReleaseChildren(m_SubDevice);
206 }
207 #endif
208
209 Irp->IoStatus.Status = Status;
210 Irp->IoStatus.Information = 0;
211 IoCompleteRequest(Irp, IO_NO_INCREMENT);
212
213 return STATUS_SUCCESS;
214 }
215
216 NTSTATUS
217 NTAPI
218 CPortFilterWaveCyclic::QuerySecurity(
219 IN PDEVICE_OBJECT DeviceObject,
220 IN PIRP Irp)
221 {
222 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
223 }
224
225 NTSTATUS
226 NTAPI
227 CPortFilterWaveCyclic::SetSecurity(
228 IN PDEVICE_OBJECT DeviceObject,
229 IN PIRP Irp)
230 {
231 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
232 }
233
234 BOOLEAN
235 NTAPI
236 CPortFilterWaveCyclic::FastDeviceIoControl(
237 IN PFILE_OBJECT FileObject,
238 IN BOOLEAN Wait,
239 IN PVOID InputBuffer,
240 IN ULONG InputBufferLength,
241 OUT PVOID OutputBuffer,
242 IN ULONG OutputBufferLength,
243 IN ULONG IoControlCode,
244 OUT PIO_STATUS_BLOCK StatusBlock,
245 IN PDEVICE_OBJECT DeviceObject)
246 {
247 UNIMPLEMENTED
248 return FALSE;
249 }
250
251 BOOLEAN
252 NTAPI
253 CPortFilterWaveCyclic::FastRead(
254 IN PFILE_OBJECT FileObject,
255 IN PLARGE_INTEGER FileOffset,
256 IN ULONG Length,
257 IN BOOLEAN Wait,
258 IN ULONG LockKey,
259 IN PVOID Buffer,
260 OUT PIO_STATUS_BLOCK StatusBlock,
261 IN PDEVICE_OBJECT DeviceObject)
262 {
263 UNIMPLEMENTED
264 return FALSE;
265 }
266
267 BOOLEAN
268 NTAPI
269 CPortFilterWaveCyclic::FastWrite(
270 IN PFILE_OBJECT FileObject,
271 IN PLARGE_INTEGER FileOffset,
272 IN ULONG Length,
273 IN BOOLEAN Wait,
274 IN ULONG LockKey,
275 IN PVOID Buffer,
276 OUT PIO_STATUS_BLOCK StatusBlock,
277 IN PDEVICE_OBJECT DeviceObject)
278 {
279 UNIMPLEMENTED
280 return FALSE;
281 }
282
283 NTSTATUS
284 NTAPI
285 CPortFilterWaveCyclic::Init(
286 IN IPortWaveCyclic* Port)
287 {
288 ISubdevice * ISubDevice;
289 SUBDEVICE_DESCRIPTOR * Descriptor;
290 NTSTATUS Status;
291
292 // get our private interface
293 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
294 if (!NT_SUCCESS(Status))
295 return STATUS_UNSUCCESSFUL;
296
297 // get the subdevice descriptor
298 Status = ISubDevice->GetDescriptor(&Descriptor);
299
300 // store subdevice interface
301 m_SubDevice = ISubDevice;
302
303 if (!NT_SUCCESS(Status))
304 return STATUS_UNSUCCESSFUL;
305
306 // save descriptor
307 m_Descriptor = Descriptor;
308
309 // allocate pin array
310 m_Pins = (IPortPinWaveCyclic**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveCyclic*), TAG_PORTCLASS);
311
312 if (!m_Pins)
313 return STATUS_UNSUCCESSFUL;
314
315 // store port driver
316 m_Port = Port;
317
318 return STATUS_SUCCESS;
319 }
320
321
322 NTSTATUS
323 NTAPI
324 CPortFilterWaveCyclic::FreePin(
325 IN struct IPortPinWaveCyclic* Pin)
326 {
327 ULONG Index;
328
329 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
330 {
331 if (m_Pins[Index] == Pin)
332 {
333 m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
334 m_Pins[Index]->Release();
335 m_Pins[Index] = NULL;
336 return STATUS_SUCCESS;
337 }
338 }
339 return STATUS_UNSUCCESSFUL;
340 }
341
342
343 NTSTATUS
344 NewPortFilterWaveCyclic(
345 OUT IPortFilterWaveCyclic ** OutFilter)
346 {
347 CPortFilterWaveCyclic * This;
348
349 This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWaveCyclic(NULL);
350
351 if (!This)
352 return STATUS_INSUFFICIENT_RESOURCES;
353
354 This->AddRef();
355
356 // return result
357 *OutFilter = (IPortFilterWaveCyclic*)This;
358
359 return STATUS_SUCCESS;
360 }
361